某天我发现我的服务器cpu占用异常的大,于是拿spark简单分析了一下

服务器信息:

服务器也就装了66个模组,没人的情况下,CPU大的十分的不正常

虽然CPU 占用高通常由 模组/插件本身算法、实体堆积、高频红石、区块加载过多 等原因引起,但是我在游戏内发现tps有时又比较稳定

获取spark的分析报告

我在终端中输入 /spark profiler --start ,在游戏跑图了一会等了大概 60 秒后再输入了/spark profiler --stop

spark会在控制台吐一个链接出来,前往浏览器打开链接即可。
打开链接即见到以下页面,如图

点击火焰按钮,查看火焰图

被我用红色圆圈标记的就是了

认识火焰图

嗯嗯,我们已经成功的拿到了火焰图接下来来认识一下火焰图

认识火焰图的 4 个关键

元素含义
纵轴调用栈深度(越深表示越底层)
横轴总 CPU 占比(不是时间轴),从左到右只是累积,无先后顺序
方块宽度越宽 = 占用的总 CPU 越多
颜色Spark 默认是绿色=Java、黄色=GC、红色=编译器/JIT、橙色=Native、蓝紫=内核

读图 3 步曲

  • 找最宽方块
    把鼠标放上去,看顶部文字。
    例:net.minecraft.server.level.ChunkMap::tick 占 28 % → 区块加载/刷新区块。
    例:org.bukkit.craftbukkit.v1_20_R1.scheduler.CraftScheduler::runTaskTimer 占 22 % → 某插件高频任务。
  • 向下追溯
    点一下最宽方块,它会放大,继续看更下一层是谁调用的。
    直到出现 “类名+方法名”“某个插件包名” 为止。

分析火焰图

可以看到火焰图里最宽的“火舌”就是 BetterRTP 插件反复异步加载/卸载区块 造成的

先来逐层拆解

  • 顶层最宽(≈35 %)
    SuperRonanCraft.BetterRTP.references.rtpinfo.queueHandler.run()
    → 这是插件的 异步队列任务,每一 tick 都在调度 getChunkAtAsync
  • 第二层
    PaperLib.getChunkAtAsync()CompletableFuture.join()ForkJoinPool.managedBlock()
    → 本质是把 主线程阻塞在异步加载 上,等待磁盘 IO 完成。
    主线程被 park 后,CPU 统计到 Unsafe.parklibc.so.6,所以看上去是 native 高。
  • 第三层
    紧接着就是 ChunkMap.save()ServerChunkCache.tick()区块持久化/卸载
    说明 加载-卸载-再加载 形成 高频抖动,CPU 空转、磁盘 IO 飙升。

因为本来 BetterRTP 插件 不支持我的服务器版本,我就删了,删除后解决了我服务器CPU占用大的问题

以上就是我对我使用spark的使用方式和介绍,总结就是火焰图就是“从顶向下找最宽方块”,方块上写的类名/方法名/插件包名就是吃 CPU 的家伙,照着修即可。

前方二次元内容,在公共场合请谨慎观看


1_0gQjuawf_IMG_7477.PNG
1_0gQjuawf_IMG_7477.PNG

1_2goOapFh_IMG_7538.PNG
1_2goOapFh_IMG_7538.PNG

1_2XixTB6P_IMG_7548.JPG
1_2XixTB6P_IMG_7548.JPG