Hi all,
I’m hoping someone could help me with a problem.
I’ve made a simple application, a few thousand particles flying around bouncing off the screen borders, drawn with the SDL renderer. The drawing is straightforward immediate mode: SDL_RenderClear()
followed by a loop of SDL_SetRenderDrawColor()/SDL_RenderFillRect()
calls, and finally SDL_RenderPresent()
. I’ve noticed a strange regular frame stutter, so I added a frame time plot, and this is what I observe:
(horizontal is frames, vertical is frame time, full bar height is 16ms)
As you can see, the frame time jitters just short of 8ms, except there’s a pretty steady beat of frames longer than 12 or even 16ms. So I’ve made my built-in profiler dump stats whenever there’s a spike > 10ms:
---
2017-Jun-01 12:04:48.4670619
src/entry.d(268) [Frame]: 18 ms, 229 μs, and 6 hnsecs
src/entry.d(299) [SDL events]: 7 μs and 3 hnsecs
src/entry.d(385) [App update]: 18 ms, 174 μs, and 3 hnsecs
src/app.d(200) [update before draw]: 44 μs and 7 hnsecs
src/app.d(246) [draw with present]: 18 ms and 129 μs
src/app.d(248) [draw only]: 3 ms, 461 μs, and 9 hnsecs
---
2017-Jun-01 12:04:53.454799
src/entry.d(268) [Frame]: 17 ms and 598 μs
src/entry.d(299) [SDL events]: 6 μs and 3 hnsecs
src/entry.d(385) [App update]: 17 ms, 540 μs, and 4 hnsecs
src/app.d(200) [update before draw]: 49 μs and 7 hnsecs
src/app.d(246) [draw with present]: 17 ms, 490 μs, and 1 hnsec
src/app.d(248) [draw only]: 3 ms, 474 μs, and 8 hnsecs
---
2017-Jun-01 12:04:58.4590516
src/entry.d(268) [Frame]: 18 ms, 151 μs, and 4 hnsecs
src/entry.d(299) [SDL events]: 5 μs and 8 hnsecs
src/entry.d(385) [App update]: 18 ms, 97 μs, and 9 hnsecs
src/app.d(200) [update before draw]: 46 μs and 2 hnsecs
src/app.d(246) [draw with present]: 18 ms, 51 μs, and 1 hnsec
src/app.d(248) [draw only]: 18 ms, 36 μs, and 4 hnsecs
---
2017-Jun-01 12:05:03.4552663
src/entry.d(268) [Frame]: 13 ms, 938 μs, and 3 hnsecs
src/entry.d(299) [SDL events]: 6 μs and 8 hnsecs
src/entry.d(385) [App update]: 13 ms, 881 μs, and 5 hnsecs
src/app.d(200) [update before draw]: 52 μs and 4 hnsecs
src/app.d(246) [draw with present]: 13 ms, 828 μs, and 2 hnsecs
src/app.d(248) [draw only]: 3 ms, 471 μs, and 3 hnsecs
---
2017-Jun-01 12:05:08.4643558
src/entry.d(268) [Frame]: 19 ms, 431 μs, and 1 hnsec
src/entry.d(299) [SDL events]: 6 μs and 1 hnsec
src/entry.d(385) [App update]: 19 ms, 376 μs, and 6 hnsecs
src/app.d(200) [update before draw]: 48 μs and 3 hnsecs
src/app.d(246) [draw with present]: 19 ms, 327 μs, and 7 hnsecs
src/app.d(248) [draw only]: 3 ms and 493 μs
---
2017-Jun-01 12:05:13.4659313
src/entry.d(268) [Frame]: 12 ms and 870 μs
src/entry.d(299) [SDL events]: 6 μs and 3 hnsecs
src/entry.d(385) [App update]: 12 ms, 816 μs, and 7 hnsecs
src/app.d(200) [update before draw]: 50 μs and 2 hnsecs
src/app.d(246) [draw with present]: 12 ms and 766 μs
src/app.d(248) [draw only]: 3 ms, 474 μs, and 7 hnsecs
---
2017-Jun-01 12:05:18.4539787
src/entry.d(268) [Frame]: 20 ms, 782 μs, and 2 hnsecs
src/entry.d(299) [SDL events]: 6 μs
src/entry.d(385) [App update]: 20 ms, 726 μs, and 5 hnsecs
src/app.d(200) [update before draw]: 53 μs and 7 hnsecs
src/app.d(246) [draw with present]: 20 ms, 672 μs, and 2 hnsecs
src/app.d(248) [draw only]: 3 ms, 477 μs, and 2 hnsecs
(It’s indented by scope, outer scopes include timings of inner scopes.)
It turns out that every 5 seconds a frame takes much longer either to SDL_RenderPresent()
, or even draw (see entry #3, 12:04:58
). What’s interesting about those 5 seconds is that the timing is consistent, i.e. in this case it spikes at (real-time seconds) 03, 08, 13, 18…, and this timing remains the same between application runs. Only after I re-login to my Gnome session may I see a different timing (i.e. 01, 06, 11…).
This persists regardless of:
- windowed mode
SDL_WINDOW_FULLSCREEN_DESKTOP
SDL_WINDOW_FULLSCREEN
SDL_RENDERER_ACCELERATED
SDL_RENDERER_SOFTWARE
- actually calling
SDL_RenderPresent()
, i.e. issuing draw calls is enough. However, if I comment out mydraw()
call altogether (the[draw with present]
block), the spikes seem to disappear, though I’m yet to make an external plot to verify.
I’ve tested the app on a bare X session with just an xterm
running, and there’s no such beat there.
The steady 5 second intervals suggest this could be _NET_WM_PING
, but I am at a loss as to why the spike happens while drawing, since, if I understand correctly, the ping is taken care of by SDL_PumpEvents()
, which I call in the [SDL events]
block (I’m using the SDL_PumpEvents()/SDL_PeepEvents()
loop).
Another thought I had was this could have something to do with compositor, but it seems unusual for it to produce such regular and strictly-timed intervals, and that it persists regardless of what window mode I choose.
I’m having a hard time understanding where this stutter is coming from or how to combat it, and thus I’ll appreciate any and all suggestions.
Thanks in advance for your time and any advice!
The specs just in case:
i7-6700K, nVidia GTX 980 Ti (driver version 381.22), Gentoo Linux (kernel 4.9.16), Gnome 3.22.2, SDL 2.0.5.