LWJGL - 循环冻结的原因?
LWJGL - Reason for cyclic freezes?
我目前正在开发一款使用 LWJGL 的 2D 游戏,但我偶然发现了一些严重的性能问题。
当我渲染超过 ~100 个精灵时,window 会冻结很短的时间。我做了一些测试,发现了以下内容:
- 垂直同步启用或禁用都会出现问题
- 即使我将帧数限制在 60 也会出现问题
- 程序不仅在短时间内渲染较少的帧,渲染似乎实际上暂停了
- 没有像矩阵计算这样的其他操作会减慢程序速度
- 我已经实现了批量渲染,但似乎并没有提高性能
- 冻结的频率随着精灵数量的增加而增加
- 我的显卡驱动程序是最新的
- 尽管帧率似乎是可以接受的,但同时出现了 100 个渲染精灵,我有 ~1500 fps,有 1000 个精灵 ~200 fps
我使用一个非常基本的着色器,变换矩阵通过每次渲染调用的统一变量传递给着色器(每帧每个精灵一次)。 CPU/GPU 总线的大小应该不是问题。
我发现了一个非常相似的问题 here,但是 none 的建议解决方案对我有用。
这是我的第一个问题,如果我遗漏了一些重要信息,请告诉我。
可能是GC。
遗憾的是,Java 并不是最好的游戏语言,这要归功于 GC 并且缺少任何可以在堆栈上分配的结构,来自类似于 Java 的语言 - c# 通常是更好的选择,这要归功于更多控制内存的工具,例如堆栈分配和一般结构。
所以当使用 GC 语言编写游戏时,你应该确保你的游戏循环不会分配太多对象,在许多情况下,在其他语言中,人们经常尝试在循环中进行 0 或接近 0 的分配。
您可以为 entities/sprites 创建对象池,这样您就不会分配新对象池,只需重新使用现有对象即可。
如果它是简单的 2d 游戏,那么可能只是避免在不需要时分配对象就足够了(比如只传递两个整数而不是对象在 2d 地图上的保存位置)。
并且您应该使用探查器来确认哪些更改是值得的。
还有一些更棘手的解决方案,比如使用堆外手动分配的内存来存储一些数据而没有对象开销,但我认为简单的游戏不需要这样的解决方案。只需典型的游戏开发解决方案(如池化和避免不需要的对象)就足够了。
我目前正在开发一款使用 LWJGL 的 2D 游戏,但我偶然发现了一些严重的性能问题。 当我渲染超过 ~100 个精灵时,window 会冻结很短的时间。我做了一些测试,发现了以下内容:
- 垂直同步启用或禁用都会出现问题
- 即使我将帧数限制在 60 也会出现问题
- 程序不仅在短时间内渲染较少的帧,渲染似乎实际上暂停了
- 没有像矩阵计算这样的其他操作会减慢程序速度
- 我已经实现了批量渲染,但似乎并没有提高性能
- 冻结的频率随着精灵数量的增加而增加
- 我的显卡驱动程序是最新的
- 尽管帧率似乎是可以接受的,但同时出现了 100 个渲染精灵,我有 ~1500 fps,有 1000 个精灵 ~200 fps
我使用一个非常基本的着色器,变换矩阵通过每次渲染调用的统一变量传递给着色器(每帧每个精灵一次)。 CPU/GPU 总线的大小应该不是问题。
我发现了一个非常相似的问题 here,但是 none 的建议解决方案对我有用。
这是我的第一个问题,如果我遗漏了一些重要信息,请告诉我。
可能是GC。
遗憾的是,Java 并不是最好的游戏语言,这要归功于 GC 并且缺少任何可以在堆栈上分配的结构,来自类似于 Java 的语言 - c# 通常是更好的选择,这要归功于更多控制内存的工具,例如堆栈分配和一般结构。
所以当使用 GC 语言编写游戏时,你应该确保你的游戏循环不会分配太多对象,在许多情况下,在其他语言中,人们经常尝试在循环中进行 0 或接近 0 的分配。
您可以为 entities/sprites 创建对象池,这样您就不会分配新对象池,只需重新使用现有对象即可。
如果它是简单的 2d 游戏,那么可能只是避免在不需要时分配对象就足够了(比如只传递两个整数而不是对象在 2d 地图上的保存位置)。
并且您应该使用探查器来确认哪些更改是值得的。
还有一些更棘手的解决方案,比如使用堆外手动分配的内存来存储一些数据而没有对象开销,但我认为简单的游戏不需要这样的解决方案。只需典型的游戏开发解决方案(如池化和避免不需要的对象)就足够了。