我目前正在使用libgdx框架开发一个小型桌面java游戏。一切都很好,除了一些非常奇怪的CPU使用行为。
当使用空渲染循环运行框架背景时,我获得大约28%的CPU使用率。考虑到lbgdx也在进行一些管理,并尽可能快地调用render方法,这似乎很好。
但是这里的事情开始变得疯狂......
在绘制和更新大约200个对象时,CPU使用率会上升到大约55%。然而,Libgdx告诉我它只使用一个open gl draw调用。 CPU开销应该非常低,不应该吗? CPU使用率也不是由更新循环引起的。我已经尝试删除它,但使用率仍高达50%左右。
但情况变得更糟......
我意外地发现,当程序必须处理大量对象(大约50000)时,使用率下降到大约30%。
如果我释放大量的对象然后返回我的200个对象,CPU使用率甚至会进一步下降到~20%。
如果我重复这个过程,使用量最终将降至3%。是3%。 并且它将保持在3%。 (只要我没有分配任何其他对象。当然,使用量会增加)
总结一下:我渲染完全相同的场景。最初具有55%的CPU使用率。并且在分配和释放大量具有3%CPU使用率的对象之后。
这怎么可能发生?
起初我认为lidgdx正在使用批处理系统,它将创建批量顶点,颜色信息和纹理坐标,以最大限度地减少绘制调用的数量。 如果我将批量大小设置为每批2500个精灵,则CPU使用率将降至30% - 40%。然而,奇怪的分配和解除分配效应仍在发生。
如果有帮助的话,我还会给你更新,绘制,渲染和清除方法。
渲染方法:
@Override
public void render()
{
//the basic game loop components
//update all and draw everything
update();
draw();
//Entity.alive refers to an ArrayList containing
//all objects that'll be updated and draw in the
//render loop
System.out.println("ENTITY COUNT " + Entity.alive.size());
//and remove all the dead bodies
//from the carpet ... you know
//i can't stand blood ...
//and make some new ones, too
clear();
while((System.nanoTime() / 1000000) - time_last < 16)
{
//nothing to do here ... (imagine meme)
try
{
Thread.sleep(0, 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
time_last = System.nanoTime() / 1000000;
}
更新方法:
public void update()
{
//update all the entities
//in the "alive" ArrayList
for(Entity e: Entity.alive) e.update();
//add all entities declared
//dead to the dead list
for(Entity e: Entity.alive)
{
//not dead - nothing to do here
if(e.getState() == true) continue;
//else add to dead list!
Entity.dead.add(e);
}
}
绘制方法:
public void draw()
{
//clear the screen
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
//update the view
Draw.updateCamera();
//start a batch section
//all further calls will
//be packed an sent to
//gpu in one flush
Draw.startBatch();
//draw all living entities
for(Entity e: Entity.alive) e.draw();
//draw all the level
//geometry and sprites
Level.draw();
//ending the sprite batch
Draw.endBatch();
}
清除方法:
public void clear()
{
//remove all dead objects
for(Entity e: Entity.dead)
{
Entity.alive.remove(e);
}
//clear the array of the dead
Entity.dead.clear();
//add all the newly created
//objects to the alive list
for(Entity e: Entity.born)
{
Entity.alive.add(e);
}
//clear the creation list
Entity.born.clear();
}
我使用java 1.8.0_31-b13在eclipse 4.4.1中开发程序。 操作系统是Windows 8.1。
答案 0 :(得分:2)
你的render()方法有点奇怪。 我不知道这是否有助于疯狂的cpu时序,以下代码是不必要的,因为LibGDX本身处理16.6ms的等待时间(60Hz)本身。如果您的计时器与LibGDX计时器不匹配,可能会遇到一些麻烦。因此,您可能需要等待太长时间才能显着降低CPU负载。删除实体时,计时器将保持不同步 - &gt;减少CPU使用率。
while((System.nanoTime() / 1000000) - time_last < 16)
{
//nothing to do here ... (imagine meme)
try
{
Thread.sleep(0, 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
答案 1 :(得分:0)
好的,经过大量的阅读和一些实验后,我发现了它!
在libGDX使用的DesktopLauncher类中,程序员被要求为lwjgl init进程创建一个配置对象。像这样:
public static void main(String[] args)
{
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.width = 1920;
config.height = 1080;
config.fullscreen = true;
config.foregroundFPS = 0;
new LwjglApplication(new Controller(), config);
}
事实证明,最后一行config.foregroundFPS = 0;
至关重要。
这会禁用框架的所有尝试,以便尽可能将线程设置为休眠状态。
我强烈怀疑这种睡眠功能可以用于奇怪的CPU使用。禁用此功能后,现在使用情况正常。
不过,非常感谢您的支持! :)
答案 2 :(得分:0)
正如我发现的,这个问题与vSync和一些特定的(nVidia?)驱动程序有关。您可以使用以下代码来防止高CPU使用率:
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.vSyncEnabled = false;
除了0和60之外的任何FPS都可以使用:
LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();
config.backgroundFPS = 59;
config.foregroundFPS = 59;