JVM 游戏服务器调优
概述
游戏服务器的延迟敏感性,使 JVM 调优成为性能关键:GC 停顿直接影响对局体验。调优目标不是"吞吐最高",而是"停顿可控":在低延迟与吞吐间找到平衡。本文聚焦 GC 算法选择、堆内存分配、线程栈与 JVM 专项参数。
一、GC 算法选择
1.1 游戏服务器的 GC 诉求
游戏 GC 诉求:
低停顿(对局不能卡顿)
高吞吐(支撑在线量)
两者冲突 → 按场景取舍
场景分类:
网关/查询服务:延迟敏感 → ZGC/G1
逻辑节点:状态常驻 → G1(暂停可控)
后台统计:吞吐优先 → G1 大堆1.2 G1 与 ZGC
G1(默认):
分区化堆,可预测停顿
通过 -XX:MaxGCPauseMillis 控制目标
适合中大型堆(4-32G)
ZGC:
亚毫秒级停顿(并发回收)
适合大堆 + 超低延迟
JDK 17+ 成熟可用
代价:CPU 开销略高
选择建议:
常规游戏服 → G1(MaxGCPauseMillis=50-100)
超低延迟关键服 → ZGC
JDK 版本升级收益明显(新 GC 优化)// G1 常用参数
-XX:+UseG1GC
-XX:MaxGCPauseMillis=80
-XX:G1HeapRegionSize=8m
-XX:MaxGCPauseMillis 控制暂停目标二、堆内存分配策略
2.1 堆大小规划
堆大小依据:
在线玩家数 × 单玩家内存(状态对象)
缓存占比(对象驻留)
活动峰值(临时对象暴涨)
示例估算:
1 万在线 × 50KB 状态 ≈ 500MB(玩家数据)
加缓存/临时对象 → 堆设 4-8G
峰值预留(活动/冲榜)→ 留 30% 余量堆结构建议:
新生代:Eden + S0/S1(短命对象为主)
老年代:长驻状态(玩家缓存)
注意:
不要盲目大堆(GC 时间长)
堆外:直接内存(Netty)+ 堆内平衡2.2 对象分配优化
减少对象创建:
长驻对象复用(玩家状态池)
避免频繁装箱(Integer.valueOf 缓存)
字符串去重(重复前缀)
大对象注意:
大数组/大字符串直接进老年代
避免大对象高频创建(GC 压力)
JVM 分配优化:
-XX:+UseTLAB:线程本地分配(默认)
-XX:SurvivorRatio:新生代比例
观察 GC 日志调比例三、线程栈大小
3.1 栈大小配置
线程栈(-Xss):
默认 1M(64 位 JVM)
线程数 × 栈大小 = 保留内存
游戏场景:
线程数量多(EventLoop + 业务池)→ 栈不宜过大
深递归/复杂调用链 → 栈太小会溢出
建议:
常规 512K-1M
线程数估算:栈大小 × 线程数 < 内存预算// 线程与栈内存估算示例
线程数:1000 线程 × 512K 栈 = 500MB 预留
线程池控制线程数上限(避免无界创建)3.2 线程池规划
线程池:
IO 线程:EventLoop(核数 × 2)
业务线程:分区线程池(见消息分发)
异步线程:异步处理池(限长)
定时任务:调度线程(少量)
原则:
线程数可数(有上限)
阻塞操作不占用 IO 线程
线程命名规范(排查方便)四、JVM 参数专项配置
4.1 全套参数示例
游戏服务器 JVM 参数示例(8C16G):
-Xms8g -Xmx8g # 堆固定(避免伸缩抖动)
-XX:+UseG1GC
-XX:MaxGCPauseMillis=80
-XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m
-Xss512k
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/logs/heapdump.hprof
-XX:+ExitOnOutOfMemoryError
-XX:MaxDirectMemorySize=2g # 直接内存(Netty)关键项说明:
堆固定:避免 JVM 自动扩缩带来的抖动
直接内存:Netty 内存池需要(与堆平衡)
堆转储:OOM 时可分析
退出策略:OOM 直接退出(容器重启)4.2 启动期与运行时
启动优化:
预分配(-XX:+AlwaysPreTouch):启动时申请物理内存
CDS(类数据共享):加快启动
运行时监控:
GC 日志(-Xlog:gc*)
JFR 记录(见监控章节)
GC 告警(长停顿/频繁 Full GC)
Full GC 排查:
Full GC 频繁 → 老年代溢出/晋升问题
→ 看对象分配/内存泄漏五、实现要点
调优清单:
默认 G1,超低延迟用 ZGC
堆按在线量估算,固定大小防抖动
线程栈 512K-1M,线程数有界
OOM 转储 + 退出策略
直接内存规划(Netty)
监控 GC 停顿与频率
调优流程:
1. 压测基线(见压测章节)
2. 抓 GC 日志/JFR 分析
3. 针对瓶颈调整(停顿/吞吐)
4. 复测对比
常见坑:
盲目大堆 → 长 GC 停顿
堆伸缩抖动 → 固定堆大小
直接内存溢出 → MaxDirectMemorySize 规划
线程数无界 → 内存/CPU 失控与其他系统衔接:
GC 监控 → 监控章节
压测验证 → 压测章节
Netty 直接内存 → Netty 调优章节
OOM 分析 → 运维章节