Skip to content

Commit

Permalink
深度优化并回归G1GC
Browse files Browse the repository at this point in the history
  • Loading branch information
Yukiriri committed Sep 23, 2024
1 parent 1bc5f61 commit 9d6b08e
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 65 deletions.
29 changes: 8 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,8 @@
</div>

一个自动化选择MC通用优化的启动脚本,在同等内存分配的情况下可以比无任何优化降低更多负载<br/>
并且在使用Java21 ZGC时可以有效缓解区块内存泄漏,能控制住膨胀,这也得益于ZGC各种新设计<br/>
以我的长期测试下来,涵盖了Java11到Java21,对比了三大热门GC(G1GC SGC ZGC),测试了原版插件服到重型整合包服,可以结论出,无论是服务端还是客户端MC,Java21的分代ZGC已经可以开始接任G1GC<br/>

# 当前策略范围

|MC版本|Java标准|对应GC|
|:-|:-|:-|
|1.7+|Java8|G1GC|
|1.16+|Java11|G1GC|
|1.17+|Java17|G1GC|
|1.20.5+|Java21|ZGC|
G1GC的研究已取得突破,等我这几天更新详解<br/>
关于ZGC,就等以后慢慢研究吧()<br/>

推荐JDK:
<a href="https://adoptium.net/zh-CN/temurin/releases/">Adoptium JDK</a>
Expand Down Expand Up @@ -84,26 +75,22 @@ git pull
```
提示:在Windows平台建议把服关闭后再更新,这个涉及到win对bat读取的逆天机制

# 经验总结建议
- 关于Java进程内存占用:
- Java进程不仅仅只包括堆内存,还有非堆内存,以及外界API管理的内存
- 例如:
- 给服务端分配4G内存,在进程运行时候的内存占用大概是(堆4G + 非堆1G+ = 5G+占用)
- 给客户端分配4G内存,在进程运行时候的内存占用大概是(堆4G + 非堆1G+ + OpenGL 2G+ = 7G+占用)

- 其实Java17也可以用ZGC,但由于不能分代,每一次GC都等价于Full GC,对性能消耗比较大,所以我放弃了Java17开启ZGC
# 经验总结

- 关于Java进程内存占用:Java进程不仅仅只包括堆内存,还有非堆内存,以及外界API管理的内存
- 例如:
- 给服务端分配4G内存,在进程运行时候的内存占用大概是(堆4G + 非堆1G+ = 5G+占用)
- 给客户端分配4G内存,在进程运行时候的内存占用大概是(堆4G + 非堆1G+ + OpenGL 2G+ = 7G+占用)
- 关于TPS消耗:可以使用<a href="https://spark.lucko.me/download">spark</a>采集并导出插件/MOD占用耗时堆栈图,找出tick占用高的堆栈顺序里最先出现的插件/模组,然后怎么办不用我说()

# 学习参考

- <a href="https://aikar.co/2018/07/02/tuning-the-jvm-g1gc-garbage-collector-flags-for-minecraft">Aikar's Flags</a>
- <a href="https://github.com/YouHaveTrouble/minecraft-optimization">YouHaveTrouble/minecraft-optimization</a>
- <a href="https://dev.java/learn/jvm/tool/garbage-collection/zgc-overview/">https://dev.java/learn/jvm/tool/garbage-collection/zgc-overview/</a>
- <a href="https://flags.sh">flags.sh</a>

# 无用的吐槽

MC的内存管理着实差劲,而且再叠上JVM臭名昭著的GC这个debuff就更是双倍**,我已经不求MC的内存占用能低了,只要不内存泄漏就是万幸<br/>
其次我对垃圾回收语言也开始感到厌恶,我不觉得延缓内存释放可以提升吞吐量,因为内存回收这种事逃不了,早回收晚回收都得回收,全部集中在一起回收不还是把之前提升的吞吐量给还了回去<br/>
其次我对垃圾回收语言也开始感到厌恶,我不觉得延缓内存释放可以提升吞吐量,因为内存回收这种事逃不了,早回收晚回收都得回收,全部集中在一起回收就会造成尖峰把之前提升的吞吐量给还回去,只要是垃圾回收语言都是这个通病<br/>
然后就是垃圾回收语言的对象内存开辟一直都是向后地址开辟,不会在已回收对象的老地址上重新利用(除非后面的空间不够用),这种大缓冲区循环滚写式设计也注定内存占用不可能下去<br/>
20 changes: 9 additions & 11 deletions flags/g1gc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@

-XX:+UseG1GC
-XX:+ParallelRefProcEnabled
-XX:MaxGCPauseMillis=200
-XX:G1HeapWastePercent=5
-XX:MaxGCPauseMillis=100
-XX:G1NewSizePercent=33
-XX:G1MaxNewSizePercent=33
-XX:SurvivorRatio=4
-XX:MaxTenuringThreshold=16
-XX:G1ReservePercent=16
-XX:InitiatingHeapOccupancyPercent=40
-XX:G1RSetUpdatingPauseTimePercent=5
-XX:G1MixedGCCountTarget=4
-XX:G1MixedGCLiveThresholdPercent=90
-XX:InitiatingHeapOccupancyPercent=15
-XX:MaxTenuringThreshold=1
-XX:SurvivorRatio=32

-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40
-XX:G1ReservePercent=20
-XX:G1HeapRegionSize=8M

-XX:GCTimeRatio=9
1 change: 1 addition & 0 deletions flags/zgc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
-XX:+UseZGC
-XX:-ZProactive
-XX:+ZGenerational
-XX:ZFragmentationLimit=15
26 changes: 10 additions & 16 deletions omcsl
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ if [[ "$JAVA_VER" == "" ]]; then
if [[ $(echo $v | grep "build 21") != "" ]]; then JAVA_VER=21; fi
if [[ $(echo $v | grep "build 17") != "" ]]; then JAVA_VER=17; fi
if [[ $(echo $v | grep "build 11") != "" ]]; then JAVA_VER=11; fi
if [[ $(echo $v | grep "build 8") != "" ]]; then JAVA_VER=8; fi
fi
if [[ "$JAVA_VER" == "" ]]; then JAVA_VER=8; fi
if [[ "$JAVA_VER" == "" ]]; then echo [OMCSL][ERROR]: JAVA_BIN error && exit; fi

core_count=$(cat /proc/cpuinfo | grep "processor" | wc -l)
JAVA_OPTS="-XX:ConcGCThreads=$core_count -XX:ParallelGCThreads=$core_count"
Expand All @@ -23,29 +24,22 @@ mem_unit=${2:0-1:1}
mem_amount=${2%$mem_unit}


if [[ "${mem_unit^}" == "G" ]]; then soft_max_heap_size="$(($mem_amount*1024/4*3))"; fi
if [[ "${mem_unit^}" == "M" ]]; then soft_max_heap_size="$(($mem_amount/4*3))"; fi
JAVA_OPTS+=" -XX:SoftMaxHeapSize=$soft_max_heap_size""M"

if [[ $JAVA_VER -ge 21 && "$OMCSL_GC_FLAGS" == "" ]]; then
OMCSL_GC_FLAGS=$shell_dir/flags/zgc.txt
fi
# if [[ $JAVA_VER -ge 21 && "$OMCSL_GC_FLAGS" == "" ]]; then
# OMCSL_GC_FLAGS=$shell_dir/flags/zgc.txt
# if [[ "${mem_unit^}" == "G" ]]; then soft_max_heap_size="$(($mem_amount*1024/4*3))"; fi
# if [[ "${mem_unit^}" == "M" ]]; then soft_max_heap_size="$(($mem_amount/4*3))"; fi
# JAVA_OPTS+=" -XX:SoftMaxHeapSize=$soft_max_heap_size""M"
# fi

if [[ $JAVA_VER -ge 17 ]]; then
JAVA_OPTS+=" --add-modules=jdk.incubator.vector"
fi

if [[ $JAVA_VER -le 17 && "$OMCSL_GC_FLAGS" == "" ]]; then
if [[ $JAVA_VER -ge 8 && "$OMCSL_GC_FLAGS" == "" ]]; then
OMCSL_GC_FLAGS=$shell_dir/flags/g1gc.txt
if [[ "${mem_unit^}" == "G" ]]; then
if [[ $mem_amount -ge 12 ]]; then OMCSL_GC_FLAGS=$shell_dir/flags/g1gc.higher.txt; fi
fi
if [[ "${mem_unit^}" == "M" ]]; then
if [[ $mem_amount -ge 12000 ]]; then OMCSL_GC_FLAGS=$shell_dir/flags/g1gc.higher.txt; fi
if [[ $mem_amount -lt 250 ]]; then
if [[ "${mem_unit^}" == "M" && $mem_amount -lt 250 ]]; then
echo [OMCSL][ERROR]: Xmx \< 250M
exit
fi
fi
fi

Expand Down
28 changes: 11 additions & 17 deletions omcsl.bat
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ if "%JAVA_VER%" == "" (
for /f "delims=" %%v in ('echo %%b ^| findstr /C:"build 21"') do set JAVA_VER=21
for /f "delims=" %%v in ('echo %%b ^| findstr /C:"build 17"') do set JAVA_VER=17
for /f "delims=" %%v in ('echo %%b ^| findstr /C:"build 11"') do set JAVA_VER=11
for /f "delims=" %%v in ('echo %%b ^| findstr /C:"build 8"') do set JAVA_VER=8
)
)
if "%JAVA_VER%" == "" set JAVA_VER=8
if "%JAVA_VER%" == "" echo [OMCSL][ERROR]: JAVA_BIN error && goto :EOF

set JAVA_OPTS=-XX:ConcGCThreads=%NUMBER_OF_PROCESSORS% -XX:ParallelGCThreads=%NUMBER_OF_PROCESSORS%

Expand All @@ -23,29 +24,22 @@ set mem_amount=%2
set mem_unit=%mem_amount:~-1%
set mem_amount=%mem_amount:~0,-1%

if /i "%mem_unit%" == "G" set /a soft_max_heap_size=%mem_amount%*1024/4*3 >nul
if /i "%mem_unit%" == "M" set /a soft_max_heap_size=%mem_amount%/4*3 >nul
set JAVA_OPTS=%JAVA_OPTS% -XX:SoftMaxHeapSize=%soft_max_heap_size%M

if %JAVA_VER% GEQ 21 if "%OMCSL_GC_FLAGS%" == "" (
set OMCSL_GC_FLAGS=%~dp0\flags\zgc.txt
)
@REM if %JAVA_VER% GEQ 21 if "%OMCSL_GC_FLAGS%" == "" (
@REM set OMCSL_GC_FLAGS=%~dp0\flags\zgc.txt
@REM if /i "%mem_unit%" == "G" set /a soft_max_heap_size=%mem_amount%*1024/4*3 >nul
@REM if /i "%mem_unit%" == "M" set /a soft_max_heap_size=%mem_amount%/4*3 >nul
@REM set JAVA_OPTS=%JAVA_OPTS% -XX:SoftMaxHeapSize=!soft_max_heap_size!M
@REM )

if %JAVA_VER% GEQ 17 (
set JAVA_OPTS=%JAVA_OPTS% --add-modules=jdk.incubator.vector
)

if %JAVA_VER% LEQ 17 if "%OMCSL_GC_FLAGS%" == "" (
if %JAVA_VER% GEQ 8 if "%OMCSL_GC_FLAGS%" == "" (
set OMCSL_GC_FLAGS=%~dp0\flags\g1gc.txt
if /i "!mem_unit!" == "G" (
if !mem_amount! GEQ 12 set OMCSL_GC_FLAGS=%~dp0\flags\g1gc.higher.txt
)
if /i "!mem_unit!" == "M" (
if !mem_amount! GEQ 12000 set OMCSL_GC_FLAGS=%~dp0\flags\g1gc.higher.txt
if !mem_amount! LSS 250 (
if /i "%mem_unit%" == "M" if %mem_amount% LSS 250 (
echo [OMCSL][ERROR]: Xmx ^< 250M
goto :EOF
)
)
)

Expand Down Expand Up @@ -74,4 +68,4 @@ if %OMCSL_DEBUG% GEQ 1 (
%JAVA_BIN% -Xmx%2 !JAVA_OPTS! -XX:+PrintFlagsFinal 2>nul | findstr /C:"command line"
echo --------------------------------------------------
)
%JAVA_BIN% -Xms%2 -Xmx%2 %JAVA_OPTS% -jar %1 --nogui
%JAVA_BIN% -Xms%2 -Xmx%2 %JAVA_OPTS% -jar %1 nogui

0 comments on commit 9d6b08e

Please sign in to comment.