sgsrules's picture

GameWindow UpdateFrame Loop stutters under heavy cpu load

I started using the game window provided by opentk and my updates stutter pretty badly. I have multiple threads doing work in the update loop and the cpu usage is fairly high but my fps is generally around 30. If i move my update logic to my main render loop everything runs silky smooth. I alleviated the problem a bit by changing the GameWindow RaiseUpdateFrame method. I introduced a MaxUpdates Variable:

  if (++num_updates >= maxUpdates || TargetUpdateFrequency == 0.0)break;

instead of

  if (++num_updates >= 10 || TargetUpdateFrequency == 0.0)break;

and set it to 0. This got rid of the large stutters that happened every couple of seconds but things are still pretty choppy. The animation also seems to run slightly slower when using the update loop, which is odd since i've got both the update and render frequency locked at 30. Any recomendations? It seems like it's running choppy since the updates are running at 30 hz but they're not syncing with the frame rate. For now i've got my logic running in my render loop and i'm capping the fps at 30 to keep update speed consistent. def not an ideal solution.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
migueltk's picture

Hi, ...

I have observed something similar in my application with a value of 50 frames per second (FPS) the camera movements are not fluid, observed jumps are exacerbated when VSync = OFF.
Is it a problem in my application or is it a problem OpenTK? I have not checked, but my intuition tells me there is a problem in OpenTK when the FPS rate is low.

In other 3D applications super fluid movement observed with an FPS of 40 or 50. For example, the sauerbraten game.
Try in the future to implement the same 3D application using SDL and OpenTK to see if the problem is OpenTK.

Regards, ...

the Fiddler's picture
Quote:

The animation also seems to run slightly slower when using the update loop, which is odd since i've got both the update and render frequency locked at 30. Any recomendations?

Do not lock your render rate:

gameWindow.Run(30);

instead of

gameWindow.Run(30, 30);
sgsrules's picture
Quote:

Do not lock your render rate:

gameWindow.Run(30);

instead of

gameWindow.Run(30, 30);

I normally do this but for testing purposes i compared the performance of running

gameWindow.Run(30); //with all the logic code running game window update loop.

vs

gameWindow.Run(30, 30); //with all the logic code running in the main renderloop.

it ran fairly jerky and slightly slower when using the game window update event. I locked the framerate at 30 in the second scenario to make sure that both tests are running at the same speed since the framerate is around 40fps. Just to reiterate i only get jerky animation when i'm cpu bound.

the Fiddler's picture

Is it possible that you are creating GC pressure? Monitor your memory allocations (GC class, esp. CollectionCount & GetTotalMemory) or use a memory profiler to gather statistics. Ideally, the GC will remain idle during a level and only run when loading a new level.

Shawn Hargreaves has written an excellent blog post on GC performance. Also check out this discussion: Troubleshooting performance problems.

Most of the material written for XNA applies to OpenTK, too.

tksuoran's picture

I am also having some performance issues. I have a very simple scene, couple of boxes basically, no fancy shaders, and I have set update and render both to 20fps. No matter which kind of system I test it on, my program keeps consuming around 100% of one core in the system.

Some of the systems are high end, some are low end. I am suspecting that the GameWindow in OpenTK is doing something that ends up almost eating one whole core. And I don't quite like this.

Any suggestions?

I am using cpuCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName); to measure CPU usage of my process.

sgsrules's picture
Quote:

Is it possible that you are creating GC pressure? Monitor your memory allocations (GC class, esp. CollectionCount & GetTotalMemory) or use a memory profiler to gather statistics. Ideally, the GC will remain idle during a level and only run when loading a new level.
Shawn Hargreaves has written an excellent blog post on GC performance. Also check out this discussion: Troubleshooting performance problems.
Most of the material written for XNA applies to OpenTK, too.

Thanks for the tips, but i'm positive it's not do to GC pressure. I don't allocate any memory unless i'm loading, and i've profiled the crap out of my app and the GC rarely runs, if ever. I suspect that the culprit is that the update and render loop aren't syncing up properly. When i run my update logic in the same loop as my render logic things sync up: update, render,update, render etc. but when i use the the update event, it does something like this: update, render, update, render,render, update, update, render. It's similar to having vsync turned off, when render frequency does match your monitors refresh rate. This isn't really an issue when things are running really fast but once the frame rate drops to around 40 or less it becomes noticeable and causes the animation to stutter and slow down a bit. I use my application to render video to disk, whenever i'm ready to render something and save it to disk i have a switch that calls the update logic before the renderer since the frame rate drops considerably while saving to disk and i need to make sure i don't skip any frames. I can switch between running the update logic through the event or calling it before the renderer whenever i want, this is how i noticed the speed difference. Things run ok when using the update event, but they run so much more fluid when i run them both in the same loop and lock the frame rate to 30.

My main questions are:
1) how are these events triggered? I know there's a timer setup that triggers the events but what happens when both the frame rate and update speeds are set to 30? Which one gets triggered first ?
2) Would switching to a different timer make a difference? Maybe use a more accurate timer.
3) Would triggering the update event asynchronously on a separate thread help?
4) Most importantly, can this even be fixed or am i always going to get smoother animation when I have everything running in the same loop? (Which isn't a big deal as long as the framerate doesn't change)

Quote:

I am also having some performance issues. I have a very simple scene, couple of boxes basically, no fancy shaders, and I have set update and render both to 20fps. No matter which kind of system I test it on, my program keeps consuming around 100% of one core in the system.
Some of the systems are high end, some are low end. I am suspecting that the GameWindow in OpenTK is doing something that ends up almost eating one whole core. And I don't quite like this.
Any suggestions?
I am using cpuCounter = new PerformanceCounter("Process", "% Processor Time", p.ProcessName); to measure CPU usage of my process.

Try profiling your app to see whats using up your cpu. Setup timers throughout your code to see whats taking the longest. Also don't lock the frame rate or use vsync as these can also increase cpu usage and give you false results.

the Fiddler's picture
Quote:

I am also having some performance issues. I have a very simple scene, couple of boxes basically, no fancy shaders, and I have set update and render both to 20fps. No matter which kind of system I test it on, my program keeps consuming around 100% of one core in the system.

Either enable vsync or call System.Threading.Thread.Sleep() to reduce your CPU usage.

the Fiddler's picture
Quote:

1) how are these events triggered? I know there's a timer setup that triggers the events but what happens when both the frame rate and update speeds are set to 30? Which one gets triggered first ?
2) Would switching to a different timer make a difference? Maybe use a more accurate timer.
3) Would triggering the update event asynchronously on a separate thread help?
4) Most importantly, can this even be fixed or am i always going to get smoother animation when I have everything running in the same loop? (Which isn't a big deal as long as the framerate doesn't change)

1) The events are measured independently, i.e. each uses a different timer. The ordering of the events is not guaranteed - only (a) the timing and (b) that UpdateFrame takes precedence over RenderFrame when the system cannot keep up with the load. Check the "RaiseUpdateFrame" and "RaiseRenderFrame" methods in Source/OpenTK/GameWindow.cs.

2) OpenTK relies on System.Diagnostics.Stopwatch which is the most accurate timer available.

3) This is certainly possible. Check the "GameWindow Threaded" sample in Examples.exe -> TK.

4) Please file a bug report so I don't forget about the issue. This is a 900000 loc project, it's impossible to keep track of everything without bug reports as a reminder!

I will of course fix the issue, provided I can reproduce it and find a plausible solution. That said, you certainly do not have to use the built-in timing code if you are not happy with it. You can turn it off by calling Run() (without arguments) and override OnUpdateFrame/OnRenderFrame to add you own timing code. Or move your rendering code to a different thread like #3 above.

Personally, I regret adding the rate limiter on RenderFrame, it was a bad design decision. My suggestion for smooth movement is this: use a fixed UpdateFrame rate (i.e. Run(30)), leave RenderFrame unlimited (preferably vsynced) and use interpolation to smooth things out. A RenderFrame rate limited to 30fps will cause jerkiness on any monitor not running at exactly 60Hz (my Samsung TFT for instance, which works at 59.9Hz, or my Nec CRT, which runs at 85Hz).

tksuoran's picture
the Fiddler wrote:

Either enable vsync or call System.Threading.Thread.Sleep() to reduce your CPU usage.

1. I thought GameWindow was internally messing around with vsync. Is vsync disabled by default and will GameWindow not mess around with vsync if I explicitly enable or disable vsync by the application?

2. What is going on if I don't sleep? Is GameWindow just busywaiting somewhere even after update and render is done and there is some time left before next update/render? What would be the correct place to add the Sleep()? My update?

3. If I set update and render to run at the same frequency, will the run one after each other in synchronized, predictable manner? This would be kind of desirable

4. I'm planning to set update frequency to 100Hz. I have physics that kind of works not so well with lower frequency. I also plan to enable vsync and leave rendering frequency unlimited. Would this work well, or is there any possible issues here? Would this be sufficient to not to eat all CPU from one core, or do I still need to add Sleep() somewhere?

the Fiddler's picture
tksuoran wrote:
the Fiddler wrote:

Either enable vsync or call System.Threading.Thread.Sleep() to reduce your CPU usage.

1. I thought GameWindow was internally messing around with vsync. Is vsync disabled by default and will GameWindow not mess around with vsync if I explicitly enable or disable vsync by the application?

Initial vsync mode depends on the OS and driver settings. OpenTK will respect your choice if you set it to VSyncMode.Enabled or VSyncMode.Disabled.

Quote:

2. What is going on if I don't sleep? Is GameWindow just busywaiting somewhere even after update and render is done and there is some time left before next update/render? What would be the correct place to add the Sleep()? My update?

OpenTK runs a busy loop. Due to the asynchronous nature of the GPU, the best place to sleep is right after your SwapBuffers call.

Quote:

3. If I set update and render to run at the same frequency, will the run one after each other in synchronized, predictable manner? This would be kind of desirable

No guarantees, unless you run on a realtime OS and give OpenTK realtime priority. Otherwise, RenderFrame events may be dropped due to peaks in CPU load and timing (scheduling) jitter. Raising your thread priority might help.

Quote:

4. I'm planning to set update frequency to 100Hz. I have physics that kind of works not so well with lower frequency. I also plan to enable vsync and leave rendering frequency unlimited. Would this work well, or is there any possible issues here? Would this be sufficient to not to eat all CPU from one core, or do I still need to add Sleep() somewhere?

That's the suggested design. Vsync should reduce CPU usage but this depends solely on the drivers (there are drivers that busy loop instead of sleeping). I know for a fact that Nvidia and Ati drivers behave well in this regard.

If you are CPU-bound, you might wish to look into moving your physics or your OpenGL rendering to a different thread. This will improve performance on dual-core machines, but your application design will become more complex.