【问题标题】:LWJGL - Reason for cyclic freezes?LWJGL - 循环冻结的原因?
【发布时间】:2020-03-11 19:28:40
【问题描述】:

我目前正在开发一个使用 LWJGL 的 2D 游戏,但我偶然发现了一些严重的性能问题。 当我渲染超过 100 个精灵时,窗口会冻结很短的时间。我做了一些测试,我发现了以下内容:

  • 启用或禁用 Vsync 都会出现问题
  • 即使我将帧设置为 60 也会出现问题
  • 程序不只是在短时间内渲染较少的帧,渲染似乎实际上暂停了
  • 没有其他操作(如矩阵计算)会减慢程序速度
  • 我已经实现了批量渲染,但似乎并没有提高性能
  • 冻结的频率随着 Sprite 的数量而增加
  • 我的显卡驱动程序是最新的
  • 我使用一个非常基本的着色器,转换矩阵通过统一变量传递给着色器每次渲染调用(每帧每个精灵一次)。 CPU/GPU 总线的大小应该不是问题。

    我发现了一个非常相似的问题here,但建议的解决方案都不适合我。

    这是我在这里的第一个问题,如果我遗漏了一些重要信息,请告诉我。

【问题讨论】:

  • 这可能是由于垃圾回收周期造成的。使用 -verbose:gc 启动 JVM 或使用内存分析器获取有关垃圾收集发生及其暂停时间的信息。
  • @httpdigest 谢谢你的回答,垃圾收集实际上是问题所在。当我每次更新都运行 System.gc() 时,不再发生冻结,但帧率明显降低,因为 gc 每次更新需要 0.005 秒。这里可能是什么问题?如何找出哪些对象不断填满堆?
  • 使用内存分析器来识别热路径中过多的对象分配(“热路径” = 每帧调用频率最高的调用树)。

标签: java performance graphics game-engine lwjgl


【解决方案1】:

这可能是 GC。

遗憾的是,由于 GC 和缺乏可以在堆栈中分配的任何结构,来自类似于 Java 的语言,Java 并不是最好的游戏语言 - c# 通常是更好的选择,因为有更多的工具来控制内存,比如堆栈分配和一般的结构。 因此,在使用 GC 语言编写游戏时,您应该确保游戏循环不会分配太多对象,在许多情况下,在其他语言中,人们经常尝试在循环中进行 0 或接近 0 的分配。
您可以为您的实体/精灵创建对象池,因此您无需分配新的,只需重新使用现有的。

如果它是简单的 2d 游戏,那么可能只是在不需要时避免分配对象就足够了(比如只传递两个整数而不是 2d 地图上的对象保存位置)。

您应该使用分析器来确认哪些更改是值得的。
还有更棘手的解决方案,比如使用堆外手动分配的内存来存储一些数据而没有对象开销,但我认为简单的游戏不需要这样的解决方案。仅典型的游戏开发解决方案(例如池化和避免不需要的对象)就足够了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 2012-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多