Using LibGdx, I recently implemented a grid system(spatial partitioning) to optimize performance for collision detection. I spawned 2000 entities on the board, and had them move around, recalculating their new tile location on the grid, and transferring the entity to the correct Collection whenever necessary.
Problem:
GC_FOR_ALLOC freed 3068K (65765), 45% free 3925K/7124K, paused 36ms, total 36ms occurs on Android around once a second, causing the rendering to stutter.
Code:
This is run by each entity:
if(newgridy!=currentgridy||newgridx!=currentgridy){ try { my_tile.remove(this); my_tile = grid[newgridy][newgridx]; my_tile.add(this); }catch (ArrayIndexOutOfBoundsException e){ } } newgridy,newgridx,currentgridy,currentygridx are tile coordinates(not render coords)
my_tile is an ArrayList
grid is a 2D array of ArrayLists
My Attempts:
I know that this is the problematic block of code, because the GC calls go away when I comment it out.
I think that the repetitive remove and add calls results in fragmented memory, and the ArrayList grows too large to fit in any contiguous location in memory, so the GC has to compact when my Entities enter a new tile. I thought I should preallocate space for each tile, but each tile could potentially contain 1000+ ships at once, and sometimes be completely empty. Then I would have to allocate the 1000 to accommodate for when it is full, but then that would be an enormous waste when the tile is empty.
Questions
Is fragmented memory my issue? If so, is there a Collection in Java that can be non-contiguous? Or other ways to fix it?
Would switching to a Quadtree for optimization help?
Sorry for multiple questions and being a bit broad.