总览

MineCraft是一个很好的例子,说明何时堆外内存确实可以提供帮助。

关键要求是:

保留的数据大部分是一个简单的数据结构(在我的世界的情况下,它的很多字节[])

堆外内存的使用可以隐藏在抽象中。

考试

我使用以下测试从零开始从种子启动Minecraft服务器,这对于服务器来说是特别昂贵的操作。

  • 在server.properties中预设种子级别= 114
  • 删除世界*目录
  • 使用以下选项启动服务器,以查看GC的工作-Xloggc:gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps
  • 与一位客户联系
  • 表演 /世界村
  • 执行 /全部保存
  • 出口。

为了分析日志,我正在使用jClarity的Censum。

标准矿山Craft.io

它有两个特别昂贵的功能:

  • 它在许多字节[]中缓存块级
  • 它尝试无限制地缓存用于处理的int []。

以上测试的Censum报告如下:

我的世界java国际版存档路径_数据结构

高暂停时间部分是由于必须管理大型对象。

离堆MineCraft

为解决此问题进行了两项更改:

  • 使用堆外ByteBuffer进行长期缓存。 不安全会更有效,但不那么可移植。
  • 对缓存的int []的数量设置上限。

注意:临时int []的问题仅在将大量数据移出堆之后才对我可见。 解决最大的问题将揭示更多的快速修复问题。

相同测试的Censum报告如下所示:

我的世界java国际版存档路径_数据结构_02

还有一些过早的升级,即可以进行进一步的改进,但是您可以看到该应用程序正在花钱。

结论

使用堆外内存可以帮助您驯服GC暂停时间,尤其是如果您的大部分数据都位于可以轻松抽象的简单数据结构中时。 这样做还可以帮助您揭示其他一些简单的优化方法,可以用来提高性能的一致性。

脚注

许多组织将性能视为增强功能和可选功能,但是,如果您灌输要求合理性能的文化,而不能满足此要求则是一个错误,那么性能问题很可能会得到解决。 cf https://bugs.mojang.com/browse/MC-56447

使用的来源

  • 用于测试的源在这里可用。 https://github.com/peter-lawrey/MineOffHeap
  • 生成的日志在此处可用。 https://github.com/peter-lawrey/MineOffHeap/tree/master/logs

翻译自: https://www.javacodegeeks.com/2014/06/minecraft-and-off-heap-memory.html