LibGdx GC_Concurrent running

I have a game, but it stutters at random. It makes me think that the GC is working. After looking at the code, I see many GC_CONCURRENT messages, for example 4-5 seconds.

12-04 22:14:22.018: D/dalvikvm(4757): GC_CONCURRENT freed 510K, 7% free 10139K/10823K, paused 4ms+6ms 12-04 22:14:22.288: D/dalvikvm(4757): GC_CONCURRENT freed 497K, 7% free 10139K/10823K, paused 3ms+7ms 12-04 22:14:22.558: D/dalvikvm(4757): GC_CONCURRENT freed 497K, 7% free 10139K/10823K, paused 3ms+6ms 12-04 22:14:22.823: D/dalvikvm(4757): GC_CONCURRENT freed 497K, 7% free 10139K/10823K, paused 3ms+7ms 

Ive narrowed down my culprit in my rendering class. I am just learning LibGdx (this is my first LibGdx application) and was wondering if anyone could see the problem.

 public void render(){ batch.begin(); //Draw background batch.draw(skin.getSprite("background_chapter"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT); //draw tiles bIter = world.getBlocks().iterator(); while(bIter.hasNext()){ tile = bIter.next(); switch(tile.getType()){ case Values.ICE: continue; (many more cases...) } batch.draw(skin.getSprite(tr), tile.getPosition().x*scaleX, tile.getPosition().y*scaleY, tile.getBounds().width*scaleX, tile.getBounds().height*scaleY); } //put ice on top of other level elements, non mobile ice on bottom bIter = world.getBlocks().iterator(); while(bIter.hasNext()){ tile = bIter.next(); if(tile.getType() == Values.ICE && tile.getCollide() == false){ batch.draw(skin.getSprite("ice"), tile.getPosition().x*scaleX, tile.getPosition().y*scaleY, tile.getBounds().width*scaleX, tile.getBounds().height*scaleY); } } //mobile ice on top bIter = world.getBlocks().iterator(); while(bIter.hasNext()){ tile = bIter.next(); if(tile.getType() == Values.ICE && tile.getCollide() == true){ batch.draw(skin.getSprite("ice"), tile.getPosition().x*scaleX, tile.getPosition().y*scaleY, tile.getBounds().width*scaleX, tile.getBounds().height*scaleY); } } //pauly on top batch.draw(skin.getSprite("pauly_moving"), pauly.getBounds().x*scaleX, pauly.getBounds().y*scaleY, pauly.getBounds().width*scaleX, pauly.getBounds().height*scaleY); batch.draw(skin.getSprite("background_chapter"), 0+(SIDE_EDGE*scaleX), (9.6f*scaleY), CAMERA_WIDTH, 1*scaleY); //draw UI elements batch.draw(skin.getSprite("pause_menu_icon"), CAMERA_WIDTH-(SIDE_EDGE*scaleX), CAMERA_HEIGHT-(0.25f*scaleY), 1*scaleX, 1*scaleY); batch.draw(skin.getSprite("restart_menu_icon"), SIDE_EDGE*scaleX, CAMERA_HEIGHT-(0.25f*scaleY), 1*scaleX, 1*scaleY); font.draw(batch, "Moves: "+pauly.getCurrentMoves()+"/ "+world.getLevel().getMovesNeeded(), 2f*scaleX,10.1f*scaleY); font.draw(batch, world.getLevel().getTitle(), 6f*scaleX,10.1f*scaleY); //draws the FPS on screen font.draw(batch, "FPS: "+(Gdx.graphics.getFramesPerSecond()), 12f*scaleX,10.1f*scaleY); if(world.getState()==Values.PAUSED){ batch.draw(skin.getSprite("pause_menu"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT); //Gdx.app.log("WorldRenderer", "Game Paused"); } else if(world.getState()==Values.LOOSE){ batch.draw(skin.getSprite("die_menu"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT); //Gdx.app.log("WorldRenderer", "Game Paused"); } else if(world.getState()==Values.WIN){ batch.draw(skin.getSprite("win_menu"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT); //Gdx.app.log("WorldRenderer", "Game Paused"); } batch.end(); } 

Ive tried commenting on blocks, and it seems like I get GC calls everywhere, although more in the middle.

EDIT: ANSWER

Using the answers below, I used DDMS to see the selection. He created about 100 new objects per second ... float [], texture area, sprite ... all related

 skin.getSprite("texture"); 

each call made float [], texture area and sprite. So thanks for distributing DDMS. The solution was what Yul said, creating sprites (fields) in the constructor function, then using them in a line.

so that...

 batch.draw(skin.getSprite("background_chapter"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT); 

changed to this ...

 //in constructor() background = skin.getSprite("background_chapter"); //in render() batch.draw(background, 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT); 

Now there are no more GC calls, and the game seems smoother.

thanks

+6
source share
1 answer

Use the Tracking Allocation Tracker tool to track where problems are occurring. (Run the application on the Android device, open the DDMS window, go to the Allocation Tracker tab, select your process on the "Devices" tab, go to the game, click "start tracking", wait a couple of seconds, click "get selection" "Look at the table data, I think sorting on threadId is a great way to isolate the activity of the rendering thread from other background threads.)

Iterators create temporary objects, especially in the rendering loop, you should use explicit indexing.

String concatenation also creates temporary objects.

There are probably many other subtle places that memory is allocated to, but the right way to figure this out is to use the right tools.

+3
source

All Articles