I’m having a little problem while making a game, and while the problem is not limited to game-programming as such, I’ll express it with the specific example I’m experiencing:
As expected, I’m running the game code in a loop, controlling game logic and drawing a frame each cycle. However, I’m experiencing quite some amount of jitter in the amount of time it takes to complete each cycle. The normal cycle time varies by about a factor of two between the shortest and longest measured time, and sometimes (more rarely), larger spikes appear that take noticable time.
I would like to eliminate both. I would like to eliminate the normal jitter to make drawing smoother, and I want to eliminate the spikes because they are noticable and annoying. The problem is, I don’t know what code is causing them to appear. I have tried measuring a couple of specific codepaths or collecting system resource usage, but it’s only helping so far.
What I would like to do, is to be able to run a CPU-profiler, resetting its counter data each cycle. That way, I could easily compare from frame to frame where time is spent and which codepaths jitter more or less in themselves. But how do I do this? I’m experiencing the problem in both Java and C, and Java’s -Xprof option and GCC’s gprof program print measured times only from the start to end of the program lifetime (as expected). Is there any way I can dump and reset these profilers’ data each cycle and/or are there some other profilers I could try that offer that ability? I also think both of them only take about 100 samples/second, which is very insufficient resolution when a frame only takes some 10-20 ms. Is there any way to turn up their sampling rate?
Alternatively, of course — is there some completely other way I could go about to solving these problems?
Let’s consider the C code, so we’re not including GC time.
I assume the excess time is not happening on every frame, but pretty seldom, so any profiler that just measures aggregate times is not going to tell you much.
What I would do (and this might not be easy) is try to tell what the program is doing only when it’s running over, not all the time.
If possible, at the start of each frame, I would set an alarm clock timer, set to go off a sufficient number of milliseconds later so that it would trigger somewhere in that extra time.
Then at the end of computing the frame, I would disable the timer so it wouldn’t go off after the frame was finished.
It might be useful to add a small random number of milliseconds to the timer.
Then when the timer goes off, I would collect a stack sample and study it to see what the program is doing.
It’s probably hard to collect samples and save them up to look at afterward.
It’s probably easier and more informative to simply enter a debugger when the alarm goes off, and study the stack and what the program’s doing right at that time.
To get another sample, either just resume execution or start over from the beginning.
The point being, you want to know what it’s doing and why it’s doing it in that excess time.
You are hoping the excess work it’s doing, or some of it, is happening in that excess time.
You might need up to 20 samples before you see something interesting,
but as soon as more than one sample shows something happening that you didn’t really realize it was doing, and you can get rid of, that will reduce the excess time usage by a significant amount.
The fewer samples you have to take before you see that, the more the time will be reduced.
There is probably more than one such issue, so don’t stop after the first thing you find.
Do it over and over until you can’t find anything that you could remove.