由 ChatGPT 生成的文章摘要
本文介绍了正在开发的Minecraft服务器插件VanillaRT。该插件是一个体素模型光线追踪引擎。在测试过程中发现,复杂的渲染任务可能导致服务器崩溃,因此需要对光线追踪的资源进行限制,从而避免主线程卡顿。为了实现这一目标,文章提出了一种算法来限制Minecraft线程池中运行的任务数,并同时最大化资源的利用。该算法依靠监测服务器的TPS(每秒滴答数)来感知资源使用情况,确保TPS保持在一个设定的阈值以上。算法分为三个阶段:试探阶段,快速增加最大并发任务数;卡顿避免阶段,在TPS下降时调整增加速度;最终,当TPS连续降低时,迅速降低任务数以恢复服务器状态。该算法受TCP拥塞控制机制启发,旨在以动态方式维持资源使用率,同时避免服务器卡顿和崩溃。
一、背景
VanillaRT 是我们最近正在开发的一款 Minecraft 服务器插件,是一个体素模型光线追踪引擎。这是一张测试时的渲染效果:
最近测试时,发现有些复杂渲染任务会导致服务器崩溃。这是因为渲染场景时需要大量的运算,而 Minecraft 服务器有一个主线程(Server Thread),主线程卡顿会导致玩家体验大幅下降,甚至因为不能及时喂狗(feed)而触发服务器崩溃。因此我们需要限制用于光追的资源,避免主线程卡顿乃至崩溃。
二、问题定义
限制光追使用的资源,关键在于限制其同时在 Minecraft 线程池里运行的任务数,并最大化资源的使用。
资源的使用可以通过检测服务器的 TPS(Tick Per Second)感知到。一般地,TPS = 20 时服务器的运行状态良好,TPS < 18 时资源就有些告急,玩家可以感受到卡顿。所以,我们的算法应当保证 TPS 不能降得太低,以避免主线程卡顿和崩溃。
具体地,算法的目标是最大化并发任务数,同时尽量保证 TPS 大于一个阈值。
三、算法
这一模型很容易让人想到 TCP 的拥塞控制。它的目标是最大化吞吐量的同时,避免拥塞。而我们的目标是最大化并发任务数,同时避免 TPS 小于警戒值。所以我们不妨简单回顾一下 TCP 的拥塞控制,其主要的思路是:
- 在资源非常充足时,我们快速(比如按指数增长速度)增加资源的使用量(慢开始)。
- 在资源可能不足(即超过阈值),但并未收到不足的信号时,我们仍然增加资源的使用量,但增加速度降低(比如转变为线性增长)。
- 在资源已经不足时,我们快速降低资源使用率,以便系统尽快恢复正常。
如此系统便可以维持资源使用率的动态最大化,同时避免拥塞。
因此我们设计一个类似的算法:
- 试探阶段:当前最大并发任务数
maxConcurrency
从一个初始值initialMaxConcurrency
开始增长。我们每次将maxConcurrency
更新为maxConcurrency * 2
,即每次翻一倍。 - 卡顿避免:当检测到
minTps < currentTps < threshTps
,我们转换到卡顿避免算法。我们每次将maxConcurrency
更新为maxConcurrency + ratio * (currentTps - minTps)
。 - 轻微卡顿恢复:当
threshStuchProb < P(currentTps < minTps) < maxStuckProb
,意味着服务器已经出现轻微卡顿。我们将maxConcurrency
减小到maxConcurrency / 2
,并切换到卡顿避免算法。 - 严重卡顿恢复:当
P(currentTps < minTps) > maxStuckProb
,意味着服务器已经出现严重卡顿。我们将maxConcurrency
重置为initialMaxConcurrency
并更新threshTps
为发生卡顿时的tps
与正常值20
的中点。
我们没有快重传和快恢复,因为我们我们检测的是 currentTps < minTps
的概率,只要当此概率超过指定值才认为服务器卡顿,消除了 TPS 随机波动的影响。
四、代码
代码写完了再更新。