Search code examples
javaperformancegraphicsgame-enginelwjgl

LWJGL - Reason for cyclic freezes?


I am currently working on a 2D Game that uses LWJGL, but I have stumbled across some serious performance issues. When I render more than ~100 sprites, the window freezes for a very small amount of time. I did some tests and I found out the following:

  • The problem occurs with both Vsync enabled or disabled
  • The problem occurs even if I cap the frames at 60
  • The program is not just rendering less frames for a short time, the Rendering seems to actually pause
  • There are no other operations like Matrix-Calculations that slow down the program
  • I already have implemented batch rendering, but it does not seem to improve the performance
  • The frequency of the freezes increases with the amount of Sprites
  • My Graphics Card driver is up to date
  • The problem occurs although the framerate seems to be quite acceptable, with 100 rendered sprites at the same time, I have ~1500 fps, with 1000 sprites ~200 fps

I use a very basic shader, the transformation matrices are passed to the shader via uniform variables each rendering call (Once per sprite per frame). The size of the CPU/GPU bus shouldn't be an issue.

I have found a very similar issue here, but none of the suggested solutions work for me.

This is my first question here, please let me know if I am missing some important information.


Solution

  • It's probably GC.

    Java is sadly not the best language for games thanks to GC and lack of any structures that can be allocated at stack, from languages similar to Java - c# is often better choice thanks to much more tools to control memory, like stack alloc and just structures in general. So when writing game in languages with GC you should make sure your game loop does not allocate too many objects, in many cases in other languages people often try to go for 0 or near 0 allocations in loop.
    You can create objects pools for your entities/sprites, so you don't allocate new ones, just re-use existing ones.

    And if it's simple 2d game, then probably just avoiding allocating objects when there is no need to should be enough (like passing just two ints instead of object holding location on 2d map).

    And you should use profiler to confirm what changes are worth it.
    There are also more tricky solutions, like using off heap manually allocated memory to store some data without object overhead, but I don't think simple game will need such solutions. Just typical game-dev solutions like pooling and avoiding not needed objects should be enough.