Proof of concept for Tracy integration #2061
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This is not a real pull request, but just a proof of concept for now. Tracy is an incredible profiler which is perfect for games because it's real time and has native support for concepts like frames.
I'll say right away that I have very limited experience with CMake and the current way to build this is incredibly stupid.
Here's how to make this build:
public
folder and unzip it assrc/libraries/tracy
src/libraries/tracy/TracyClient.cpp
:So, what do you get with this? Well, Tracy is an instrumentation based profiler, so by instrumenting all the little Lua wrappers we can immediately provide incredibly helpful information for all lövers - with no work on their part.
For lövers that want to instrument their Lua code, Tracy actually has built-in support for Lua.
All we need is that
tracy::LuaRegister(L);
call and now we can use the tracy library.Here is an example main.lua:
As you can see, I've made a terrible mistake here - I'm calling newImage inside love.draw.
I've attached the resulting .tracy trace file here: love_overusing_newImage.zip
(Note that Tracy files are locked to the version it was made in, in this case 0.10)
To view this saved trace, either
As you can see, we have a nice frame counter at the top and if we zoom in we can see what's taking so long inside our draw function:
If we then move that to a love.load we can use the Compare function inside Tracy to see how much faster our draw function is now:
Right now, Tracy is set to be "on-demand", that is, it should have a very minimal impact on performance until a profiler is connected.
Ideally this could just be in every love.exe, but there are some questions like network discovery (because Tracy can work over the network) and such that doesn't make sense to enable for everyone...Perhaps a separate executable should be shipped, love_tracy or something like that which can be used when a developer wants to profile a game.
The Tracy API provides a function
tracy::LuaRemove(char* script)
which can be used to automatically strip any Lua calls to tracy before the code is loaded, for example, when launching in an executable where Tracy is disabled.Ideally the default love.run should include the tracy.Zone.... markings for load, draw and update so you don't need to write it yourself.
Tracy also supports grabbing graphical frame data which it can display in the log. The default example on the website linked above shows this feature off. I did not add this in the proof of concept.
To prevent profiling from being used unless called for,Perhaps a new item can be added to love.conf such astracy_mode
:"disabled"
(default) Do not connect to any profiler"on_demand"
Start running as normal and connect to a profiler if one requests it"wait"
Wait until a profiler is connected before starting the game (for when you need to debug your love.load or something)Finally, I would like to show you this excellent video which goes into way more detail into what Tracy is and what makes it awesome.
https://www.youtube.com/watch?v=ghXk3Bk5F2U (slides: https://github.com/CppCon/CppCon2023/blob/main/Presentations/Tracy_Profiler_2024.pdf)
That also goes into why building it in a special way is necessary here.