【发布时间】:2023-03-17 07:15:02
【问题描述】:
我目前正在使用 libgdx 框架开发一个小型桌面 java 游戏。一切都很好,除了一些非常奇怪的 CPU 使用行为。
当只运行带有空渲染循环的框架背景时,我得到大约 28% 的 CPU 使用率。考虑到 lbgdx 也在做一些管理并且尽可能快地调用渲染方法,这似乎很好。
但这里的事情开始变得疯狂......
当绘制和更新大约 200 个对象时,CPU 使用率会上升到大约 55%。然而,Libgdx 告诉我它只使用一个 open gl 绘图调用。那么 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();
}
我正在使用 java 1.8.0_31-b13 在 eclipse 4.4.1 中开发程序。 操作系统为 Windows 8.1。
【问题讨论】:
-
你如何测量 CPU 使用率?
-
CPU 使用率是否与您的帧率相关?
-
标记为此代码不起作用的人需要重新阅读标记说明。这是一个完全有效的问题,虽然很长而且有点罗嗦。
-
对 OP 也是如此:这完全是对编码风格的评论,但是您有点过分评论了。
Entity.dead.clear()非常简单,并不值得评论。它增加了很多模糊,否则应该用于 cmets 解释不那么微不足道的部分。只是一个想法:) -
感谢您的辩护! :) 我知道有点罗嗦,但很难用几句话来描述这个问题。关于评论:你是绝对正确的。过度注释代码的倾向只是我在大学时养成的习惯。因为很多不同的人会阅读你的代码,而分数有时取决于那些人对程序的理解,所以为了安全起见,我倾向于评论每一点。
标签: java opengl libgdx cpu-usage