The “call graph time measurer”, hereafter called ScopeTimer, is a simple fire-and-forget timer, much like the scoped mutex in boost. The constructor parameter to the ScopeTimer is a data container which knows about some basic stuff like start time, delta time, and also has a name and knowledge of parent and children. I keep all data thread safe by thread local storage. Around the ScopeTimer I added a convenience macro like so:
#define MEASURE_SCOPE(name) \
static const string _name_(strutil::fmt(#name ";" __FILE__ ";%i", __LINE__)); \
static const std::hash
static const size_t _hash_ = (_hasher_)(_name_); \
ScopeTimer _timer_(ScopeData::insert(_name_, _hash_));
When all the data is collected for a frame I can unfold the call tree for each thread I’m interested in, and print it out. Printing is an ok solution if all you have access to is a text console (i.e. server side). On the graphical side I added a cheeky renderer which takes the times for the scopes and plots them as line segments each frame, with a history of 100 frames or so. The result is a live feed on what scope is causing delays:
The pink part is "waiting for physics to finish this frame" and purple part is the graph rendering itself (highly unoptimized) and the green part is "sleeping until frame time over". The black graph just below is physics times.
I also added a printout of all the names that appear in the call graph, in the same color as their respective line segment, and what file/line they where declared on. Jitter detection is now a walk in the park, along with what's causing it.
Although the idea was easy enough it still took me a couple of days+nights to get everything set up - but I would definitely recommend it!
Oops: 07:03. Time to go to bed. Unemployment is good again! ;)