-
Notifications
You must be signed in to change notification settings - Fork 112
Tracy Profiling
-
Download Tracy, unzip it anywhere: https://github.com/wolfpld/tracy/releases/tag/v0.9.1
-
Get the exact engine version we are currently using from https://engine-builds.beyondallreason.dev/index.html
-
Find the exact engine version folder we are currently using in BAR/data/engine
4A. Rename the old spring.exe to spring_vanilla.exe, and extract spring.exe from the archive to this engine folder.
5A. Start BAR as you would otherwise via the lancher.
4B. Unzip the engine to BAR/data/engine
5B. Get the BAR Debug Launcher exe file from here: https://github.com/beyond-all-reason/bar_debug_launcher/tree/main . Install it to BAR root folder (next to beyond-all-reason.exe)
6B. In the BAR Debug launcher, select the tracy engine build you unzipped in step 2, and select "Spring-launcher with rapid://byar-chobby:test"
6B. Hit Start in the BAR Debug launcher
- Launch Tracy.exe, and hit connect. If it throws an instrumentation error, connect again.
- Analyze profile.
Tracy can benefit from additional manual instrumentation to allow for very accurate profiling. By default, the engine does provide a good coverage of of zones. On the image below, the yellow zones are mostly from the engine, while the blue zones are generally from BAR's widgethandler.
Using the provided docker build environment, enable tracy via:
./build.sh -o -t RELEASE -C -DTRACY_ENABLE=1
The rules of adding zones are the following:
- Always call
tracy.ZoneEnd()
, if you have multiple return paths from a function, then addtracy.ZoneEnd()
to all of them - The lines with
tracy.*
get removed from the lua files in non-tracy enabled builds, so they dont cost performance. - Remember to name your zones in
tracy.ZoneBeginN()
Below is an example of nesting zones:
function gadgetHandler:GameFrame(frameNum)
-- Since GameGrame should never be called nested ensure here the callinDepth
-- is ok. We set it to 1 so after the run it will be set to 0 again.
callinDepth = 1
tracy.ZoneBeginN("G:GameFrame")
for _, g in ipairs(self.GameFrameList) do
tracy.ZoneBeginN("G:GameFrame:" .. g.ghInfo.name)
g:GameFrame(frameNum)
tracy.ZoneEnd()
end
tracy.ZoneEnd()
return
end
Here is the result of the above annotation:
Note that there are two consecutive G:GameFrame zones, one for synced and one for unsynced.
By default, all messages that go through Recoil's logging system, including Spring.Echo()
also generate tracy messages. This is very useful because the exact time stamp and approximate call stack of the message can be inferred from this. Also, messages can be searched.
To use, specify a message in Lua like so:
if tracy then
tracy.Message(string.format("spawnCreepStructure: Failed to spawn %s at %d*%d*%d ", unitDefName, spawnPosX, spawnPosY, spawnPosZ ))
end
Messages can be viewed and clicked in the messages tab of the Tracy UI, see:
You can plot data in an extremely accurate way (and quickly) and view it side-by-side with the traces by initializing and plotting data.
/*** Initialize a plot in Tracy for use in debugging or profiling
*
* @function tracy.LuaTracyPlotConfig
* @string plotName which should be initialized
* @string[opt] plotFormatType "Number"|"Percentage"|"Memory", default "Number"
* @bool[opt] step stepwise chart, default true is stepwise
* @bool[opt] fill color fill, default false is no fill
* @number[opt] color unit32 number as BGR color, default white
* @treturn nil
*/
/*** Update a Tracy Plot with a value
*
* @function tracy.LuaTracyPlot
* @string plotName which LuaPlot should be updated (must have been initialized via LuaTracyPlotConfig)
* @number plotvalue the number to show on the Tracy plot
* @treturn nil
*/
For example, lets say we wanted to plot the lua memory usage of the engine on every update:
if tracy and tracy.LuaTracyPlotConfig then
tracy.LuaTracyPlotConfig("LuaRAM", "memory")
end
function widgetHandler:Update()
if tracy and tracy.LuaTracyPlot then
tracy.LuaTracyPlot("LuaRAM", collectgarbage("count"))
end
...
See a wide view of the plot:
See how accurate the plot is, also giving us a delta value on mouseover: