使用LibGdx在Java中使用opengl奇怪的CPU
我目前正在使用libgdx框架开发一个小型桌面java游戏。一切都很好,除了一些非常奇怪的CPU使用行为
当只在框架后台运行一个空的渲染循环时,我得到了大约28%的CPU使用率。考虑到lbgdx也在做一些管理,并且渲染方法被尽可能快地调用,这似乎很好
但现在事情开始变得疯狂
当绘制和更新大约200个对象时,CPU使用率会上升到大约55%。然而,Libgdx告诉我它只使用一个opengldraw调用。CPU开销应该很低,不是吗?此外,CPU使用率不是由更新循环引起的。我已经试过删除它,但使用率仍然高达50%左右
但情况变得更糟
我偶然发现,当程序必须处理大量对象(大约50000个)时,使用率下降到30%左右
如果我取消分配大量的对象,然后回到我的200个对象,CPU使用率将进一步下降到约20%
如果我重复这个过程,使用率最终会下降到3%。是的,3%。 它将保持在3%。(只要我不分配任何其他对象,那么使用率当然会增加)
总而言之:我正在渲染完全相同的场景。起初,CPU使用率为55%。在分配和取消分配大量CPU使用率为3%的对象之后
这怎么可能发生
起初,我认为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();
}
我正在使用Java1.8.0\u31-b13在Eclipse4.4.1中开发程序。 操作系统是Windows 8.1
# 1 楼答案
正如我发现的,这个问题与vSync和一些特定的(nVidia?)有关司机。您可以使用以下代码来防止高CPU使用率:
除0和60工程外的任何FPS:
# 2 楼答案
您的render()方法有点奇怪。 我不知道这是否会导致疯狂的cpu计时下面的代码是不必要的,因为LibGDX本身处理16.6ms的等待时间(60Hz)。如果您的计时器与LibGDX计时器不匹配,可能会出现一些问题。因此,您可能会等待太长时间,从而显著降低cpu负载。删除实体时,计时器将保持不同步->;减少cpu使用
# 3 楼答案
好的,经过大量的阅读和实验,我终于明白了
在libGDX使用的DesktopLauncher类中,要求程序员为lwjgl init进程创建一个config对象。大概是这样的:
最后一行
config.foregroundFPS = 0;
很关键。 这将尽可能禁用框架将线程设置为睡眠的所有尝试我强烈怀疑这种睡眠功能是对奇怪的CPU使用负责的。禁用此选项后,使用行为现在正常
不过,非常感谢您的支持!:)