Excessive Memory Consumption
Hello,
I’ve been working on a project with this library and have encountered a significant issue with memory usage. Even in a basic application, the memory footprint seems to be expanding considerably. Upon investigation, I suspect the problem lies in the frequent object instantiation within the game loop, like Vector2 and Rectangle used in the DrawTexture functions. These objects are being created anew in each frame, which could be leading to the increased memory usage.
Does anyone have a workaround or a solution to mitigate this memory growth?
I thought about using Memory Stack, but it only works for primitive types, which would involve significantly changing the source code, or using object pooling, but I don't know if it would be a good idea.
Raylib-J could do something similar that LibGDX does by mutating Vector2s directly instead of replacing them with new all the time. This will decrease Java garbage collection by a lot.
Here is their Vector2 class containing methods like set, add, scl and mul.
https://github.com/libgdx/libgdx/blob/master/gdx/src/com/badlogic/gdx/math/Vector2.java
As a workaround in your game code, you could make all the vectors you need private fields of the containing class and change their x and y fields directly (or use their setX and setY as much as possible).
Upgrading to code similar to LibGDX would help a lot to reduce memory usage, but there are still other parts that would continue to consume a lot of memory. I did a test using VisualVM on a simple raylib program and this was a snapshot of memory usage (the application ran for about a minute).
public static void main(String[] args) {
Raylib rlj = new Raylib();
rlj.core.InitWindow(800, 600, "Raylib-J Example");
Texture2D texture = rlj.textures.LoadTexture("woman.png");
rlj.core.SetTargetFPS(60);
Rectangle source = new Rectangle(0,0, texture.getWidth(), texture.getHeight());
Vector2 origin = new Vector2(0,0);
while (!rlj.core.WindowShouldClose()){
rlj.core.BeginDrawing();
rlj.core.ClearBackground(Color.WHITE);
rlj.textures.DrawTexturePro(texture, source,source,origin,0f, Color.WHITE);
rlj.text.DrawText("Hello World", 10, 10, 35, Color.GREEN);
rlj.core.EndDrawing();
}
rlj.textures.UnloadTexture(texture);
}
Snapshot: https://github.com/user-attachments/assets/7efb3ba4-6243-4e26-b879-7a226ca68857
Regarding this issue of using private vectors, they would not help much, since the application core would continue to instantiate several objects that would be unusable/unreachable in the next iteration.
Thanks for the profiling. I see that math objects are less impacting memory than I assumed at first (props for me guessing things instead of measuring...), but I'm sure they would start contributing more and more to memory and GC usage as your project grows.
Seeing as byte arrays are the most constructed object we could figure out which ones are constructed every frame and maybe consider re-using them or do some kind of pooling where possible. (Although the latter would add unwanted complexity.)
I guess it's up to the maintainers to decide if this is worth the effort worth on taking a hit at code readability for doing some less GC.
If I get unsatisfied with memory usage in my project, I'll might end up creating a branch and seeing how big or little difference this would make.