use*_*692 6 android garbage-collection libgdx
我有一个游戏运行,但它一直在随机排队.这让我觉得GC正在运行.查找代码后,我看到很多GC_CONCURRENT消息,比如4-5秒.
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
Run Code Online (Sandbox Code Playgroud)
我把我的罪魁祸首缩小到我的渲染类.我刚学习LibGdx(这是我的第一个LibGdx应用程序),并想知道是否有人能看到问题.
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();
}
Run Code Online (Sandbox Code Playgroud)
我试过评论关闭块,看起来我到处都是GC调用,虽然更多的是在中间.
编辑:答案
使用下面的答案,我使用DDMS来查看分配.它每秒制作大约100个新对象... float [],纹理区域,精灵......都与之相关
skin.getSprite("texture");
Run Code Online (Sandbox Code Playgroud)
每个调用都是一个float [],一个纹理区域和一个sprite.所以感谢DDMS分配查找.通过在构造函数中创建精灵(字段)然后使用在线调用它们,解决方案就是Yul所说的.
所以这...
batch.draw(skin.getSprite("background_chapter"), 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT);
Run Code Online (Sandbox Code Playgroud)
换到这个......
//in constructor()
background = skin.getSprite("background_chapter");
//in render()
batch.draw(background, 0+(SIDE_EDGE*scaleX), 0+(BOTTOM_EDGE*scaleY), CAMERA_WIDTH, CAMERA_HEIGHT);
Run Code Online (Sandbox Code Playgroud)
现在没有更多的GC调用,游戏似乎运行得更顺畅.
谢谢
使用 DDMS 分配跟踪器工具来跟踪具体问题所在。(在 Android 设备上运行该应用程序,打开 DDMS 窗口,切换到分配跟踪器选项卡,在“设备”选项卡中选择您的进程,让您的游戏继续运行,单击“开始跟踪”,等待几秒钟,单击“获取分配” ”,查看数据表。我发现对 threadId 进行排序是将渲染线程活动与其他后台线程隔离的好方法。)
迭代器创建临时对象,因此尤其是在渲染循环中,您应该使用显式索引。
字符串连接也会创建临时对象。
可能还有很多其他微妙的地方正在分配内存,但解决这个问题的正确方法是使用正确的工具。
| 归档时间: |
|
| 查看次数: |
795 次 |
| 最近记录: |