序言

注:本页面内容主要为官方手册"Finding the cause of lag spikes"的翻译,另包含了一部分我自己实际操作的实例。


当少量的tick(有时只是一个tick)需要很长时间来执行时,就会出现所谓的“滞后峰值”(译注:原文lag spikes,此处没找到合适的词汇替代所以直译。minecraft中一个tick正常情况下为50毫秒,当一个tick持续时间过长,就表现为卡顿。而将tick的长度画成如下的图,就表现为tick持续时间上的峰值)。

如何用spark找到卡顿的源头-第1张图片

这种情况可能发生得很频繁,例如每20个tick就有一个,也可能很少发生,例如每分钟一次。它们通常与玩家的行为有关。

仅仅从正常的剖析数据中找到滞后峰值的原因可能很棘手,因为数据是平均的。其他数据样本会“淹没”这一峰值,掩盖其带来的影响。

幸运的是,Spark有两个有用的工具来解决这个问题。


一、使用“/spark tickmonitor”指令来检测滞后峰值

为了在分析报告中确定“滞后峰值”的源头,我们需要将“峰值”对应的tick找出来。

我们可以使用/spark tickmonitor命令来做到这一点。


这个命令的工作原理是首先检测服务器的平均tick速率,然后。

1.监视每个tick的持续时间的时间

2.计算执行最后一个tick所需的时间与平均时间之间的差异(以百分比表示)。

3.如果差值超过一定的阈值,就在聊天中发送一条消息

要启用监控,只需运行/spark tickmonitor。

默认情况下,这个阈值是平均值的两倍(例如,正常情况下一个tick为50毫秒,则高于100毫秒的tick会被记录)。你也可以指定阈值为一个绝对的tick持续时间,例如/spark tickmonitor --threshold-tick 50来报告任何超过50毫秒的tick(如前所述,一个tick的时间是50ms,比这个更长的tick则可视作一次卡顿)。

如何用spark找到卡顿的源头-第2张图片

上图为一次使用该指令的范例。需要注意这里的“大于100%”是比平均值多100%的意思(比平均值多一倍,或者说是平均值的两倍)


然后,你只需要正常游玩(或者直接试着重复那些会导致你游戏卡顿的操作),并且观察聊天栏里输出的监测结果即可。

如果输出不够敏感(卡顿比较轻微,低于阈值),可以尝试一个较低的阈值,例如/spark tickmonitor --threshold-tick 70。

为了演示,这里将使用WorldEdit来制造一个“滞后峰值”。

可以看到,当对应的操作被执行的时候,一个tick的持续时间达到了通常的十倍以上。

如何用spark找到卡顿的源头-第3张图片


二、使用/spark profiler与--only-ticks-over来查找卡顿原因

--only-ticks-over选项意味着spark只对持续时间超过给定阈值的tick进行分析。这就过滤掉了所有 "正常 "的tick,只留下了卡顿时的异常tick。


你可以通过上一步的操作来确定一个合适的阈值(译注:这个指令的阈值是一个tick持续的绝对时间),我建议使用50到100之间的值--但它应该总是小于卡顿时一个tick的持续时间。

例如,在上一个例子中,卡顿发生时的一个tick持续了超过300毫秒,但只是为了确保它们会被包括在内,我将使用一个较低的阈值150毫秒。

然后执行对应指令,比如说,/spark profiler --only-ticks-over 150。

这将开始新的一轮监测,但只记录持续时间超过150ms的tick,例如——

如何用spark找到卡顿的源头-第4张图片

从上图中就可以看到由“WorldEdit”造成的异常卡顿。


译者注:在通过上述指令开始监测后,需要输入/spark profiler --stop指令结束监测,这样日志才会被输出。

在日志生成后,会被自动上传到一个网页上,网址会显示在聊天栏,便于分享。


三、查找卡顿原因的实例

这里以我个人的一个存档为例,当时由于mod冲突,我从储物抽屉中取出物品时会异常卡顿。

我通过上一节所提到的/spark profiler指令生成了一份日志(参见:Profile at 下午07:10 2022/8/19 (lucko.me))。

如何用spark找到卡顿的源头-第5张图片这里我们直接点击红框中的按钮,切换到source模式。

然后就可以看到造成延迟的mod被按照影响从高到低的顺序进行了排序,卡顿的源头就被找到了。