<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=Engine_Profiling</id>
	<title>Engine Profiling - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://www.fightorder.net/wiki/index.php?action=history&amp;feed=atom&amp;title=Engine_Profiling"/>
	<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Engine_Profiling&amp;action=history"/>
	<updated>2026-04-21T05:51:38Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=Engine_Profiling&amp;diff=2185&amp;oldid=prev</id>
		<title>Qrow: 1 revision imported</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Engine_Profiling&amp;diff=2185&amp;oldid=prev"/>
		<updated>2026-02-24T06:34:52Z</updated>

		<summary type="html">&lt;p&gt;1 revision imported&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;1&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 23:34, 23 February 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-notice&quot; lang=&quot;en&quot;&gt;&lt;div class=&quot;mw-diff-empty&quot;&gt;(No difference)&lt;/div&gt;
&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;</summary>
		<author><name>Qrow</name></author>
	</entry>
	<entry>
		<id>https://www.fightorder.net/wiki/index.php?title=Engine_Profiling&amp;diff=2184&amp;oldid=prev</id>
		<title>enginedevinter&gt;Hox: /* Engine Profiling */</title>
		<link rel="alternate" type="text/html" href="https://www.fightorder.net/wiki/index.php?title=Engine_Profiling&amp;diff=2184&amp;oldid=prev"/>
		<updated>2017-05-17T22:29:30Z</updated>

		<summary type="html">&lt;p&gt;&lt;span class=&quot;autocomment&quot;&gt;Engine Profiling&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;[[Engine_Development|Development]] &amp;lt; Engine Profiling&lt;br /&gt;
&lt;br /&gt;
= Engine Profiling =&lt;br /&gt;
&lt;br /&gt;
== Linux ==&lt;br /&gt;
&lt;br /&gt;
=== Intro ===&lt;br /&gt;
There are several ways to profile an application.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;gprof&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The compiler injects special code in the binary that self profiles it when it runs. this is what &amp;lt;code&amp;gt;cmake -DCMAKE_BUILD_TYPE=PROFILING&amp;lt;/code&amp;gt; is here for. We are not going to use this. It does not interfere with normal program&amp;#039;s work-flow. With spring, it gets so slow that it is unusable for profiling anything in late game (which is where it is needed the most). It requires special compiling options.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;oprof&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
OProfile uses statistical sampling. It is a kernel module, which every n clock ticks, registers which function is currently being processed. It is lightweight; it may run with almost 0 performance impact. This method always profiles your profiles your whole system; relevant info has to be filtered out after the profiling run has finished.&lt;br /&gt;
The downside of statistical profiling, is that it requires at least a certain sample size to achieve good accuracy. Also remember, that &amp;#039;&amp;#039;oprof&amp;#039;&amp;#039; still requires the debug symbols, to resolve addresses into function names.&lt;br /&gt;
It can be turned on/off at any time, so for instance, you may skip spring loading so you would only profile in-game runtime. You can also merge multiple profiling sessions.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;perf&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Powerful and lightweight Linux performance profiler based on perf events. Part of linux kernel from version 2.6.31. &lt;br /&gt;
&lt;br /&gt;
=== Setting up &amp;#039;&amp;#039;oprof&amp;#039;&amp;#039; ===&lt;br /&gt;
&lt;br /&gt;
Required stuff:&lt;br /&gt;
* &amp;#039;&amp;#039;oprof&amp;#039;&amp;#039; kernel module&lt;br /&gt;
* &amp;#039;&amp;#039;oprof&amp;#039;&amp;#039; package&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;#039;&amp;#039;oprof&amp;#039;&amp;#039; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{|style=&amp;quot;margin-top: 15px; padding: 10px; border: 1px solid rgba(0,0,0,0.5); border-radius: 6px 6px 6px 6px; box-shadow: 0 2px 6px rgba(0,0,0,0.3), inset 0 1px 2px rgba(255,255,255,0.5), inset 0 10px 8px rgba(255,255,255,0.3);&amp;quot; |&lt;br /&gt;
| Note: Modern CPUs have special statistical sampling timing functions to make profiling with software like &amp;#039;&amp;#039;oprof&amp;#039;&amp;#039; fast.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You will have to load the kernel module.&lt;br /&gt;
The profiling daemon is controlled using &amp;#039;&amp;#039;opcontrol&amp;#039;&amp;#039; as root.&lt;br /&gt;
As regular user, you can do post-processing using &amp;#039;&amp;#039;opreport&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Recommended settings&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* use a call-graph depth of size 16&lt;br /&gt;
* disable kernel profiling &amp;amp; enable user-space profiling&lt;br /&gt;
* separate each application in its own profile&lt;br /&gt;
* separate each thread in its own profile; you can always merge them later, using &amp;#039;&amp;#039;opreport&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;A typical profiling session&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
# We need to be root&lt;br /&gt;
su -&lt;br /&gt;
&lt;br /&gt;
# In case the kernel module is not already loaded ...&lt;br /&gt;
modprobe -v oprofile&lt;br /&gt;
&lt;br /&gt;
# This has to be sent only once; it will be saved&lt;br /&gt;
opcontrol --event=CPU_CLK_UNHALTED:1000000:0x0:0:1 \&lt;br /&gt;
          --callgraph=16 \&lt;br /&gt;
          --separate=thread,library \&lt;br /&gt;
          --no-vmlinux&lt;br /&gt;
&lt;br /&gt;
# -- Bring spring into a state where you want to start profiling --&lt;br /&gt;
&lt;br /&gt;
# start the profiler&lt;br /&gt;
opcontrol --start&lt;br /&gt;
&lt;br /&gt;
# -- In spring, do whatever you want to profile --&lt;br /&gt;
&lt;br /&gt;
# stop the profiler&lt;br /&gt;
opcontrol --stop&lt;br /&gt;
&lt;br /&gt;
# in order to make the profile data available to user-space,&lt;br /&gt;
# you have to dump the data&lt;br /&gt;
opcontrol --dump&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Post processing &amp;#039;&amp;#039;oprof&amp;#039;&amp;#039; data ===&lt;br /&gt;
&lt;br /&gt;
[[File:Oprof_engine_part.png|710px]]&lt;br /&gt;
&lt;br /&gt;
We will first explain the post processing steps, and then give a script that should work for most general spring profiling tasks.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Extract the data&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
The data is now stored in &amp;#039;&amp;#039;oprofile&amp;#039;&amp;#039;s cache, and we need to extract the parts of it that we are interested in, and write them to a file.&lt;br /&gt;
With the settings we used above, &amp;#039;&amp;#039;oprofile&amp;#039;&amp;#039; indexes stuff by thread- and process-ID. In order to generate a report, we will have to tell which program, which threads and which sampling sessions to include.&lt;br /&gt;
If you do not care much, you can just merge thread data and sampling data, as we do here too.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Converting the data file to a dot-graph file&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[https://code.google.com/p/jrfonseca/wiki/Gprof2Dot gprof2dot] takes &amp;#039;&amp;#039;oprof&amp;#039;&amp;#039; data and outputs a nice dot-graph. We use it to generate the dot graph out of &amp;#039;&amp;#039;oprofile&amp;#039;&amp;#039;s &amp;lt;code&amp;gt;--callgraph&amp;lt;/code&amp;gt; version.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Finalizing (Creating an image out of the graph file)&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
Then you can either use [https://code.google.com/p/jrfonseca/wiki/XDot XDot] to view it directly, or create an image out of the graph file. We will use [http://www.graphviz.org/ GraphViz]&amp;#039;s &amp;#039;&amp;#039;dot&amp;#039;&amp;#039; utility to render to an image.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Post Processing Script&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
SPRING_INSTALL_PATH=$(dirname $(which spring))&lt;br /&gt;
BIN_ENGINE=${SPRING_INSTALL_PATH}/spring&lt;br /&gt;
BIN_AIS=$(ls ${SPRING_INSTALL_PATH}/AI/Skirmish/*/*/libSkirmishAI.so)&lt;br /&gt;
&lt;br /&gt;
SETTINGS_CREATE_TABLE=0&lt;br /&gt;
SETTINGS_CREATE_CALLGRAPH=1&lt;br /&gt;
SETTINGS_CREATE_PNG=1&lt;br /&gt;
SETTINGS_CREATE_SVG=1&lt;br /&gt;
SETTINGS_CLEANUP=1&lt;br /&gt;
&lt;br /&gt;
function profileBins() {&lt;br /&gt;
	BASE_OUT_FILE_PATH=$1&lt;br /&gt;
	MY_BINARIES=&amp;quot;$2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
	# extract relevant oprof data as table&lt;br /&gt;
	if [ ${SETTINGS_CREATE_TABLE} == 1 ]; then&lt;br /&gt;
		opreport \&lt;br /&gt;
				--long-filenames \&lt;br /&gt;
				--demangle=smart \&lt;br /&gt;
				--merge=tid,tgid \&lt;br /&gt;
				--symbols ${MY_BINARIES} \&lt;br /&gt;
				--output-file ${BASE_OUT_FILE_PATH}.txt&lt;br /&gt;
	fi&lt;br /&gt;
&lt;br /&gt;
	if [ ${SETTINGS_CREATE_CALLGRAPH} == 1 ]; then&lt;br /&gt;
		# extract relevant oprof data as callgraph&lt;br /&gt;
		opreport \&lt;br /&gt;
				--long-filenames \&lt;br /&gt;
				--callgraph \&lt;br /&gt;
				--demangle=smart \&lt;br /&gt;
				--merge=tid,tgid \&lt;br /&gt;
				--symbols ${MY_BINARIES} \&lt;br /&gt;
				--output-file ${BASE_OUT_FILE_PATH}.oprof&lt;br /&gt;
&lt;br /&gt;
		# create graph file&lt;br /&gt;
		gprof2dot --format=oprofile --output=${BASE_OUT_FILE_PATH}.dot ${BASE_OUT_FILE_PATH}.oprof&lt;br /&gt;
&lt;br /&gt;
		# create images&lt;br /&gt;
		if [ ${SETTINGS_CREATE_PNG} == 1 ]; then&lt;br /&gt;
			dot -Tpng ${BASE_OUT_FILE_PATH}.dot &amp;gt; ${BASE_OUT_FILE_PATH}.png&lt;br /&gt;
		fi&lt;br /&gt;
		if [ ${SETTINGS_CREATE_SVG} == 1 ]; then&lt;br /&gt;
			dot -Tsvg ${BASE_OUT_FILE_PATH}.dot &amp;gt; ${BASE_OUT_FILE_PATH}.svg&lt;br /&gt;
		fi&lt;br /&gt;
		# ... likewise for other formats&lt;br /&gt;
&lt;br /&gt;
		if [ ${SETTINGS_CLEANUP} == 1 ]; then&lt;br /&gt;
			rm ${BASE_OUT_FILE_PATH}.oprof&lt;br /&gt;
			rm ${BASE_OUT_FILE_PATH}.dot&lt;br /&gt;
		fi&lt;br /&gt;
	fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#profileBins ./profiling_engine         &amp;quot;${BIN_ENGINE}&amp;quot;&lt;br /&gt;
profileBins ./profiling_ais            &amp;quot;${BIN_AIS}&amp;quot;&lt;br /&gt;
profileBins ./profiling_engine_and_ais &amp;quot;${BIN_ENGINE} ${BIN_AIS}&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
This will leave you with these graph files:&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
./profiling_ais.png&lt;br /&gt;
./profiling_ais.svg&lt;br /&gt;
./profiling_engine_and_ais.png&lt;br /&gt;
./profiling_engine_and_ais.svg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using &amp;#039;&amp;#039;perf&amp;#039;&amp;#039; ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Setup&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
For ubuntu install linux-tools-common using apt-get. In fedora the package&amp;#039;s name is perf.&lt;br /&gt;
Make sure &amp;lt;code&amp;gt;/proc/sys/kernel/kptr_restrict&amp;lt;/code&amp;gt; contains value &amp;#039;&amp;#039;&amp;#039;0&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Useful commands&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* perf top - shows statistics in real time&lt;br /&gt;
* perf record - save statistics to file for further insight&lt;br /&gt;
* perf report - read previously generated data&lt;br /&gt;
* perf diff a.data b.data - show differences between two report files&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Example&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* Get data of running spring proccess for 10 seconds. Pay attention to frequency parameter -F. At this rate the output takes about 17 mb of space. Parameter call-graph dwarf unwinds the stack even when frame pointer optimization is on.&lt;br /&gt;
&amp;lt;code&amp;gt;perf record -F 99 -p PID_NUMBER -o my_output1.data --call-graph dwarf sleep 10&amp;lt;/code&amp;gt;&lt;br /&gt;
* Read the report. Press / and type symbol to narrow list to e.g &amp;quot;air&amp;quot;&lt;br /&gt;
&amp;lt;code&amp;gt;perf report -i my_output1.data -g&amp;lt;/code&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
  Children      Self  Command  Shared  Symbol                                                                                   &lt;br /&gt;
+  132.33%    29.15%  unknown  spring  [.] CStrafeAirMoveType::Update&lt;br /&gt;
+   71.36%     3.35%  unknown  spring  [.] CStrafeAirMoveType::UpdateFlying&lt;br /&gt;
+   52.01%    32.48%  unknown  spring  [.] CStrafeAirMoveType::UpdateAirPhysics&lt;br /&gt;
+   36.42%     0.00%  unknown  spring  [.] CAirCAI::ExecuteFight&lt;br /&gt;
    34.50%    12.55%  unknown  spring  [.] CommandDrawer::DrawAirCAICommands&lt;br /&gt;
+   32.11%     0.00%  unknown  spring  [.] CStrafeAirMoveType::UpdateLanding&lt;br /&gt;
    26.65%    12.90%  unknown  spring  [.] CGameHelper::GetClosestEnemyAircraft&lt;br /&gt;
    16.73%     0.00%  unknown  spring  [.] CAirCAI::GiveCommandReal&lt;br /&gt;
    15.91%     0.00%  unknown  spring  [.] CStrafeAirMoveType::FindLandingPos&lt;br /&gt;
    15.91%     6.42%  unknown  spring  [.] CStrafeAirMoveType::BrakingDistance&lt;br /&gt;
     9.82%     0.00%  unknown  spring  [.] CAirCAI::AirAutoGenerateTarget&lt;br /&gt;
     9.82%     0.00%  unknown  spring  [.] CAirCAI::SlowUpdate&lt;br /&gt;
     3.28%     0.00%  unknown  spring  [.] CAirCAI::ExecuteMove&lt;br /&gt;
     3.26%     0.00%  unknown  spring  [.] CStrafeAirMoveType::HandleCollisions&lt;br /&gt;
     3.17%     3.17%  unknown  spring  [.] AAirMoveType::UseSmoothMesh                                                &lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Flamegraph&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;perf script -i a.data | ./stackcollapse-perf.pl &amp;gt; out.perf-folded&amp;lt;/code&amp;gt; - convert perf stacks data to text representation&lt;br /&gt;
* &amp;lt;code&amp;gt;./flamegraph.pl out.perf-folded &amp;gt; my_idle_air.svg&amp;lt;/code&amp;gt; - create flamegraph from perf data&lt;br /&gt;
or&lt;br /&gt;
* &amp;lt;code&amp;gt;grep -i air out.perf-folded | ./flamegraph.pl &amp;gt; my_idle_air.svg&amp;lt;/code&amp;gt; - same as above, but it ignores stacks that do not contain &amp;quot;air&amp;quot; in symbol names&lt;br /&gt;
&lt;br /&gt;
[[File:flamegraph-grepped-example.png|flamegraph-grepped-example.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Links&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[https://perf.wiki.kernel.org/index.php/Tutorial perf kernel wiki tutorial]&lt;br /&gt;
&lt;br /&gt;
[http://www.brendangregg.com/perf.html perf examples by Brendan Gregg]&lt;br /&gt;
&lt;br /&gt;
[https://eclipse.org/linuxtools/projectPages/perf/ Eclipse perf plugin]&lt;br /&gt;
&lt;br /&gt;
[https://github.com/brendangregg/FlameGraph Flamegraph]&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;Please add&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Engine Dev]]&lt;/div&gt;</summary>
		<author><name>enginedevinter&gt;Hox</name></author>
	</entry>
</feed>