Fork of Paper 将区域化多线程添加到专用服务器。
Folia 将附近加载的块分组以形成“独立区域”。有关 Folia 如何对附近块进行分组的确切详细信息,请参阅 PaperMC 文档。每个独立区域都有自己的滴答循环,以常规 Minecraft 滴答率 (20TPS) 滴答。滴答循环在线程池上并行执行。不再有主线程,因为每个区域实际上都有自己的“主线程”来执行整个滴答循环。
对于具有许多分散玩家的服务器,Folia 将创建许多分散区域并在可配置大小的线程池上并行勾选它们。因此,Folia 应该能够很好地适应这样的服务器。
Folia也是它自己的项目,在可预见的将来不会合并到Paper中。
更详细但抽象的概述:项目概述。
自然地分散玩家的服务器类型,如 skyblock 或 SMP,将从 Folia 中受益最多。服务器也应该有相当多的玩家数量。
理想情况下,至少 16 个核心(不是线程)。
首先,建议预先生成世界,这样可以大大减少所需的块系统工作线程的数量。
以下是基于 Folia 发布之前在我们运行的测试服务器上所做的测试(峰值约为 330 名玩家)的非常粗略的估计。因此,它并不准确,需要进一步调整 - 只是将其作为起点。
应考虑机器上可用核心的总数。然后,为以下对象分配线程:
-XX:ConcGCThreads=n
标志实现的。不要将此标志与-XX:ParallelGCThreads=n
混淆,因为并行 GC 线程仅在应用程序被 GC 暂停时运行,因此不应考虑在内。完成所有分配后,系统上的剩余核心直到 80% 分配(分配的总线程数 < 可用 cpu 的 80%)可以分配给tickthreads(在全局配置下,threaded-regions.threads)。
您不应分配超过 80% 的核心的原因是插件甚至服务器可能会使用您无法配置甚至预测的其他线程。
此外,以上都是基于玩家数量的粗略猜测,但线程分配很可能并不理想,您需要根据最终看到的线程的使用情况来调整它。
没有更多的主线程。我希望现有的每个插件都需要进行一定程度的修改才能在 Folia 中运行。此外,任何类型的多线程都会在插件保存的数据中引入可能的竞争条件 - 因此,必然需要进行更改。
因此,请将您对兼容性的期望设置为 0。
目前,有很多API依赖于主线程。我预计与 Paper 兼容的插件基本上为零,与 Folia 兼容。不过,我们计划添加 API,使 Folia 插件与 Paper 兼容。
例如,Bukkit 调度程序。 Bukkit Scheduler 本质上依赖于单个主线程。 Folia 的 RegionScheduler 和 Folia 的 EntityScheduler 允许将任务调度到“拥有”位置或实体的任何区域的“下一个刻度”。这些可以在常规 Paper 上实现,除了它们调度到主线程 - 在这两种情况下,任务的执行将发生在“拥有”位置或实体的线程上。这一概念普遍适用,因为当前的论文(单线程)可以被视为一个巨大的“区域”,涵盖了所有世界中的所有块。
目前尚未决定是直接将该 API 添加到 Paper 本身还是添加到 Paperlib。
首先,Folia 破坏了许多插件。为了帮助用户确定哪些插件可以工作,只有作者明确标记为可与 Folia 配合使用的插件才会被加载。通过将“folia-supported: true”放入插件的plugin.yml中,插件作者可以将其插件标记为与区域化多线程兼容。
另一个重要的规则是这些区域是并行运行的,而不是同时运行的。他们不共享数据,也不期望共享数据,而共享数据会导致数据损坏。在任何情况下在一个区域中运行的代码都不能访问或修改另一区域中的数据。仅仅因为多线程就在名称中,并不意味着现在一切都是线程安全的。事实上,只有少数东西是线程安全的才能实现这一点。随着时间的推移,线程上下文检查的数量只会增加,即使它会带来性能损失 -没有人会使用或开发一个有很多错误的服务器平台,而防止和发现这些错误的唯一方法bugs 的目的是在错误访问的根源处使错误访问难以失败。
这意味着 Folia 兼容插件需要利用 RegionScheduler 和 EntityScheduler 等 API 来确保其代码在正确的线程上下文上运行。
一般来说,可以安全地假设一个区域拥有来自事件源的大约 8 个块中的块数据(即玩家破坏块,可能可以访问该块周围的 8 个块)。但是,这并不能得到保证 - 插件应该利用即将推出的线程检查 API 来确保正确的行为。
线程安全的唯一保证来自这样一个事实:单个区域拥有某些块中的数据 - 如果该区域正在运行,则它可以完全访问该数据。该数据具体是实体/块/poi 数据,与任何插件数据完全无关。
正常的多线程规则适用于插件存储/访问自己的数据或其他插件的数据 - 事件/命令/等。被并行调用,因为区域是并行滴答的(我们不能以同步方式调用它们,因为这会导致死锁问题并会影响性能)。没有简单的方法可以解决这个问题,这完全取决于正在访问的数据。有时并发集合(如 ConcurrentHashMap)就足够了,但通常不小心使用并发集合只会隐藏线程问题,从而几乎无法调试。
要正确理解 API 添加,请阅读项目概述。
要正确理解 API 添加,请阅读项目概述。
一般经验法则:
在拥有实体/玩家的区域上调用实体/玩家的命令。控制台命令在全局区域上执行。
涉及单个实体的事件(即玩家打破/放置方块)在区域拥有实体上调用。涉及实体操作的事件(例如实体损坏)在拥有目标实体的区域上调用。
事件的 async 修饰符已被弃用 - 从区域或全局区域触发的所有事件都被视为synchronous ,即使不再有主线程。
< repository >
< id >papermc</ id >
< url >https://repo.papermc.io/repository/maven-public/</ url >
</ repository >
< dependency >
< groupId >dev.folia</ groupId >
< artifactId >folia-api</ artifactId >
< version >1.20.1-R0.1-SNAPSHOT</ version >
< scope >provided</ scope >
</ dependency >
PATCHES-LICENSE 文件描述了 api 和服务器补丁的许可证,除非另有说明,可在./patches
及其子目录中找到。
该分叉基于此处找到的 PaperMC 分叉示例。因此,它包含在该项目中对其进行的修改,请参阅存储库以获取修改文件的许可证信息。