- Notifications
You must be signed in to change notification settings - Fork492
Fork of Paper which adds regionised multithreading to the dedicated server.
License
PaperMC/Folia
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Folia groups nearby loaded chunks to form an "independent region."Seethe PaperMC documentation for exact details on how Foliawill group nearby chunks.Each independent region has its own tick loop, which is ticked at theregular Minecraft tickrate (20TPS). The tick loops are executedon a thread pool in parallel. There is no main thread anymore,as each region effectively has its own "main thread" that executesthe entire tick loop.
For a server with many spread out players, Folia will create manyspread out regions and tick them all in parallel on a configurable sizedthreadpool. Thus, Folia should scale well for servers like this.
Folia is also its own project, this will not be merged into Paperfor the foreseeable future.
A more detailed but abstract overview:Project overview.
Server types that naturally spread players out,like skyblock or SMP, will benefit the most from Folia. The servershould have a sizeable player count, too.
Ideally, at least 16cores (not threads).
First, it is recommended that the world is pre-generated so that the numberof chunk system worker threads required is reduced greatly.
The following is avery rough estimation based off of the testingdone before Folia was released on the test server we ran thathad ~330 players peak. So, it is not exact and will require further tuning -just take it as a starting point.
The total number of cores on the machine available should betaken into account. Then, allocate threads for:
- netty IO :~4 per 200-300 players
- chunk system io threads: ~3 per 200-300 players
- chunk system workers if pre-generated, ~2 per 200-300 players
- There is no best guess for chunk system workers if not pre-generated, ason the test server we ran we gave 16 threads but chunk generation was stillslow at ~300 players.
- GC Settings: ???? But, GC settingsdo allocate concurrent threads, and you needto know exactly how many. This is typically through the
-XX:ConcGCThreads=n
flag. Do notconfuse this flag with-XX:ParallelGCThreads=n
, as parallel GC threads only run whenthe application is paused by GC and as such should not be taken into account.
After all of that allocation, the remaining cores on the system until 80%allocation (total threads allocated < 80% of cpus available) can beallocated to tickthreads (under global config, threaded-regions.threads).
The reason you should not allocate more than 80% of the cores is due to thefact that plugins or even the server may make use of additional threadsthat you cannot configure or even predict.
Additionally, the above is all a rough guess based on player count, butit is very likely that the thread allocation will not be ideal, and youwill need to tune it based on usage of the threads that you end up seeing.
There is no more main thread. I expectevery single pluginthat exists to requiresome level of modification to functionin Folia. Additionally, multithreading ofany kind introducespossible race conditions in plugin held data - so, there are boundto be changes that need to be made.
So, have your expectations for compatibility at 0.
Currently, there is a lot of API that relies on the main thread.I expect basically zero plugins that are compatible with Paper tobe compatible with Folia. However, there are plans to add API thatwould allow Folia plugins to be compatible with Paper.
For example, the Bukkit Scheduler. The Bukkit Scheduler inherentlyrelies on a single main thread. Folia's RegionScheduler and Folia'sEntityScheduler allow scheduling of tasks to the "next tick" of whateverregion "owns" either a location or an entity. These could be implementedon regular Paper, except they schedule to the main thread - in both cases,the execution of the task will occur on the thread that "owns" thelocation or entity. This concept applies in general, as the current Paper(single threaded) can be viewed as one giant "region" that encompassesall chunks in all worlds.
It is not yet decided whether to add this API to Paper itself directlyor to Paperlib.
First, Folia breaks many plugins. To aid users in figuring out whichplugins work, only plugins that have been explicitly marked by theauthor(s) to work with Folia will be loaded. By placing"folia-supported: true" into the plugin's plugin.yml, plugin authorscan mark their plugin as compatible with regionised multithreading.
The other important rule is that the regions tick inparallel, and notconcurrently. They do not share data, they do not expect to share data,and sharing of datawill cause data corruption.Code that is running in one region under no circumstance canbe accessing or modifying data that is in another region. Justbecause multithreading is in the name, it doesn't mean that everythingis now thread-safe. In fact, there are only afew things that weremade thread-safe to make this happen. As time goes on, the numberof thread context checks will only grow, evenif it comes at aperformance penalty -nobody is going to use or develop for aserver platform that is buggy as hell, and the only way toprevent and find these bugs is to make bad accesses failhard at thesource of the bad access.
This means that Folia compatible plugins need to take advantage ofAPI like the RegionScheduler and the EntityScheduler to ensuretheir code is running on the correct thread context.
In general, it is safe to assume that a region owns chunk datain an approximate 8 chunks from the source of an event (i.e. playerbreaks block, can probably access 8 chunks around that block). But,this is not guaranteed - plugins should take advantage of upcomingthread-check API to ensure correct behavior.
The only guarantee of thread-safety comes from the fact that asingle region owns data in certain chunks - and if that region isticking, then it has full access to that data. This data isspecifically entity/chunk/poi data, and is entirely unrelatedtoANY plugin data.
Normal multithreading rules apply to data that plugins store/accesstheir own data or another plugin's - events/commands/etc. are calledinparallel because regions are ticking inparallel (we CANNOTcall them in a synchronous fashion, as this opens up deadlock issuesand would handicap performance). There are no easy ways out of this,it depends solely on what data is being accessed. Sometimes aconcurrent collection (like ConcurrentHashMap) is enough, and often aconcurrent collection used carelessly will onlyhide threadingissues, which then become near impossible to debug.
To properly understand API additions, please readProject overview.
- RegionScheduler, AsyncScheduler, GlobalRegionScheduler, and EntityScheduleracting as a replacement for the BukkitScheduler.The entity scheduler is retrieved via Entity#getScheduler, and therest of the schedulers can be retrieved from the Bukkit/Server classes.
- Bukkit#isOwnedByCurrentRegion to test if the current ticking regionowns positions/entities
To properly understand API additions, please readProject overview.
General rules of thumb:
Commands for entities/players are called on the region which ownsthe entity/player. Console commands are executed on the global region.
Events involving a single entity (i.e player breaks/places block) arecalled on the region owning entity. Events involving actions on an entity(such as entity damage) are invoked on the region owning the target entity.
The async modifier for events is deprecated - all eventsfired from regions or the global region are consideredsynchronous,even though there is no main thread anymore.
- Most API that interacts with portals / respawning players / someplayer login API is broken.
- ALL scoreboard API is considered broken (this is global state thatI've not figured out how to properly implement yet)
- World loading/unloading
- Entity#teleport. This will NEVER UNDER ANY CIRCUMSTANCE come back,use teleportAsync
- Could be more
- Proper asynchronous events. This would allow the result of an eventto be completed later, on a different thread context. This is requiredto implement some things like spawn position select, as asynchronouschunk loads are required when accessing chunk data out-of-region.
- World loading/unloading
- More to come here
- Super aggressive thread checks across the board. This is absolutelyrequired to prevent plugin devs from shipping code that may randomlybreak random parts of the server in entirelyundiagnosable manners.
- More to come here
- Maven Repo (for folia-api):
<repository> <id>papermc</id> <url>https://repo.papermc.io/repository/maven-public/</url></repository>
- Artifact Information:
<dependency> <groupId>dev.folia</groupId> <artifactId>folia-api</artifactId> <version>1.20.1-R0.1-SNAPSHOT</version> <scope>provided</scope></dependency>
The PATCHES-LICENSE file describes the license for api & server patches,found in./patches
and its subdirectories except when noted otherwise.
The fork is based off of PaperMC's fork example foundhere.As such, it contains modifications to it in this project, please see the repository for license informationof modified files.