本帖最后由 世界边境 于 2023-11-10 11:16 编辑
在MC上启用新的垃圾收集器:ZGC
作者:1ByteBit
翻译:世界边境
本文原地址:https://github.com/1ByteBit/ZGC-For-Minecraft
前言需要注意一点,过去人们认为ZGC必须针对设备及程序的具体情况进行微调。在JAVA17之前的版本里确实是这样,但是现在相关的参数已经可以由程序自动设定了。因此,我们并不需要追求过分细致的配置。
ZGC是什么?ZGC全称为Z Garbage Collector,一种垃圾回收机制(简称GC)。简单来讲,GC可以清理内存中的垃圾数据,将内存空间释放出来。
存在有多种GC,并且有很多相关参数设定能够决定它们如何运行。过去有很多人在使用Aikars(paper服务端的作者)设计的那组参数,尽管它已经非常好了,但是Aikars的参数仍然需要服务器“暂停一下”来进行垃圾回收,这种暂停可能会导致卡顿。ZGC解决了这个问题,它与并行于主程序,这样不必每次进行垃圾回收都要暂停一下。译者的补充:Aikars设计的这组参数已经是2018年的事情了,它在当时使用了先进的G1GC作为垃圾收集器,相比更旧的GC而言,具有相当大的提升。而且几乎可以保证不会因为GC而导致主程序卡顿。但这组参数是针对JAVA8设计的,那时1.18.2还未发布,等到java17被MC玩家大规模使用,已经是2022年的事情了。尽管Aikars的参数仍对高版本JAVA有相当不错的效果(参考这里),我们也应该与时俱进的尝试引入一些“现代化”的新东西,比如ZGC。
谁可以使用ZGC?ZGC需要分配大量内存,因此ZGC最适合于能够分配至少8GB以上内存的服务器。不过,请注意ZGC还没有进行过广泛的测试,可能会消耗比这更多内存空间,因此,内存越大越好。
换句话说,也只有那些有很大内存的服务器可以使用ZGC。
译者的补充:ZGC使用了一种称为“染色指针”的机制来实现,但问题在于,染色指针不仅占用了更高的内存空间,也会使用更多的CPU。在传统的G1GC,它让主程序暂停以进行GC,当TPS达到20时,只要GC设置合理,服务器在两个tick之间总会有足够的时间来进行GC操作(即GC的时间不长于50ms)。而在ZGC,它与主程序同步进行GC,虽然它暂停主程序的时间不会超过10ms,但会一直使用CPU,如果是在线程数比较少的设备上,将导致ZGC占用主程序的CPU资源,最终导致TPS更低。所以ZGC不止要求更大的内存,也要求有更多的线程数。保险起见,建议内存满足12G及以上,CPU满足4线程及以上。
ZGC参数建议:java -Xms8G -Xmx8G -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:+PerfDisableSharedMem -XX:-ZUncommit -XX:+ParallelRefProcEnabled -jar server.jar --nogui请了解,使用其他参数可能会导致:1. 提高整体的CPU使用率,获得极小的GC性能提升。2. 降低整体的CPU使用率,但是可能会使GC不堪重负。总的来讲,最好不要更改这些参数,除非你确切的知道自己在做什么,并存在更改它的具体缘由。
唯一的例外是:-XX:+UseLargePages,由于这一参数需要对服务器系统进行一些设置,我没有将其包含在以上参数中。译者的补充:启用-XX:+UseLargePages,需要在Linux上启用大页面,请参考这里
重要提醒:· 将 -Xmx/-Xms 改为你想给MC分配的内存数量。· 把 server.jar 该为你用的服务器核心文件名称。· “+”表示该参数被专门启用,而“-”表示该参数被专门禁用。
每个参数的作用:参数作用-Xms and -Xmx matching它防止了因操作系统从JAVA回收内存而导致的可能存在的问题,并避免GC因内存堆大小变化产生额外工作量-XX:+UnlockExperimentalVMOptions其他参数的依赖项-XX:+UseZGC启用ZGC-XX:+DisableExplicitGC防止插件或其他代码干扰GC-XX:+AlwaysPreTouch启动时设置并预分配内存,提高了效率和访问速度-XX:+PerfDisableSharedMem防止GC写入文件系统,减少由于IO造成的延迟。具体请看这里-XX:-ZUncommit防止ZGC取消内存限制,并将其返还给操作系统-XX:+ParallelRefProcEnabled以Aikars的话来说:“优化GC进程,使用多个线程进行弱引用检查。不确定为什么这不是默认的…”
ZGC可用的其他参数:
关于通用参数,请参阅此文参数作用-XX:+UseLargePages字面上来看,提高性能且没有什么缺点,只是需要在操作系统中进行正确设置-XX:+UseTransparentHugePages这个参数的功能为启用透明大页面。以Aikars的话来说: "有争议的功能,但如果你无法在自己的设备上配置真正的大页面,就会有所帮助。我们还不清楚透明大页面如何在MC上工作,也没有衡量它对AlwaysPreTouch的影响,因此,这是为那些想要进行实验的高级用户准备的。"-XX:ConcGCThreadsGC使用的线程数,默认动态配置-XX:ZAllocationSpikeToleranceZGC的分配峰值容差,默认数值为2,数值越大,分配率更高-XX:ZCollectionInterval发生ZGC的最短时间间隔,默认为0-XX:ZFragmentationLimit如果当前区域中的碎片占比高于此值,则将回收此区域(默认为25)-XX:ZMarkStackSpaceLimit指定标记堆栈可以分配的最大字节数,默认为8589934592 (8096M)-XX:ZProactive是否启用主动回收,默认为true-XX:UseNUMA启用NUMA支持,默认情况下根据设备情况自动启用,使用此参数可以强制启用/禁用-XX:ZUncommitDelay设置对内存在未提交之前,必须的处于空闲状态的时常(必须启用ZUncommit),默认为300
主要来源:
Purpur DiscordAikars的参数Oracle官方文档/OracleOpenJDK WikiDev.java
备注:有一个新世代的ZGC版本,就像是G1GC之于旧世代GC,它可能需要更多调整以保证稳定性,并且我还没有对它进行过适当的测试,如果你想尝试一下,可以在"-XX:+UseZGC"参数后加上"-XX:+ZGenerational"。
在MC上启用新的垃圾收集器:ZGC
作者:1ByteBit
翻译:世界边境
本文原地址:https://github.com/1ByteBit/ZGC-For-Minecraft


存在有多种GC,并且有很多相关参数设定能够决定它们如何运行。过去有很多人在使用Aikars(paper服务端的作者)设计的那组参数,尽管它已经非常好了,但是Aikars的参数仍然需要服务器“暂停一下”来进行垃圾回收,这种暂停可能会导致卡顿。ZGC解决了这个问题,它与并行于主程序,这样不必每次进行垃圾回收都要暂停一下。译者的补充:Aikars设计的这组参数已经是2018年的事情了,它在当时使用了先进的G1GC作为垃圾收集器,相比更旧的GC而言,具有相当大的提升。而且几乎可以保证不会因为GC而导致主程序卡顿。但这组参数是针对JAVA8设计的,那时1.18.2还未发布,等到java17被MC玩家大规模使用,已经是2022年的事情了。尽管Aikars的参数仍对高版本JAVA有相当不错的效果(参考这里),我们也应该与时俱进的尝试引入一些“现代化”的新东西,比如ZGC。

换句话说,也只有那些有很大内存的服务器可以使用ZGC。
译者的补充:ZGC使用了一种称为“染色指针”的机制来实现,但问题在于,染色指针不仅占用了更高的内存空间,也会使用更多的CPU。在传统的G1GC,它让主程序暂停以进行GC,当TPS达到20时,只要GC设置合理,服务器在两个tick之间总会有足够的时间来进行GC操作(即GC的时间不长于50ms)。而在ZGC,它与主程序同步进行GC,虽然它暂停主程序的时间不会超过10ms,但会一直使用CPU,如果是在线程数比较少的设备上,将导致ZGC占用主程序的CPU资源,最终导致TPS更低。所以ZGC不止要求更大的内存,也要求有更多的线程数。保险起见,建议内存满足12G及以上,CPU满足4线程及以上。

唯一的例外是:-XX:+UseLargePages,由于这一参数需要对服务器系统进行一些设置,我没有将其包含在以上参数中。译者的补充:启用-XX:+UseLargePages,需要在Linux上启用大页面,请参考这里



关于通用参数,请参阅此文参数作用-XX:+UseLargePages字面上来看,提高性能且没有什么缺点,只是需要在操作系统中进行正确设置-XX:+UseTransparentHugePages这个参数的功能为启用透明大页面。以Aikars的话来说: "有争议的功能,但如果你无法在自己的设备上配置真正的大页面,就会有所帮助。我们还不清楚透明大页面如何在MC上工作,也没有衡量它对AlwaysPreTouch的影响,因此,这是为那些想要进行实验的高级用户准备的。"-XX:ConcGCThreadsGC使用的线程数,默认动态配置-XX:ZAllocationSpikeToleranceZGC的分配峰值容差,默认数值为2,数值越大,分配率更高-XX:ZCollectionInterval发生ZGC的最短时间间隔,默认为0-XX:ZFragmentationLimit如果当前区域中的碎片占比高于此值,则将回收此区域(默认为25)-XX:ZMarkStackSpaceLimit指定标记堆栈可以分配的最大字节数,默认为8589934592 (8096M)-XX:ZProactive是否启用主动回收,默认为true-XX:UseNUMA启用NUMA支持,默认情况下根据设备情况自动启用,使用此参数可以强制启用/禁用-XX:ZUncommitDelay设置对内存在未提交之前,必须的处于空闲状态的时常(必须启用ZUncommit),默认为300

Purpur DiscordAikars的参数Oracle官方文档/OracleOpenJDK WikiDev.java
