Folia groups nearby loaded chunks to form an "independent region." See the PaperMC documentation for exact details on how Folia will group nearby chunks. Each independent region has its own tick loop, which is ticked at the regular Minecraft tickrate (20TPS). The tick loops are executed on a thread pool in parallel. There is no main thread anymore, as each region effectively has its own "main thread" that executes the entire tick loop.
For a server with many spread out players, Folia will create many spread out regions and tick them all in parallel on a configurable sized threadpool. Thus, Folia should scale well for servers like this.
Folia is also its own project, this will not be merged into Paper for 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 server should have a sizeable player count, too.
Ideally, at least 16 cores (not threads).
To get the best performance from Folia, it's recommended that you pre-generate the world, which significantly reduces the number of chunk system worker threads needed.
Here's a rough guide based on tests with a server that reached a peak of around 330 players. Please note that this is just a starting point and may require further tuning depending on your specific situation.
First, consider the total number of cores available on your machine. Allocate threads for the following tasks:
Netty IO: Approximately 4 threads per 200-300 players
Chunk system IO threads: Approximately 3 threads per 200-300 players
Chunk system workers (if pre-generated): Approximately 2 threads per 200-300 players
For chunk system workers without pre-generation, it's difficult to provide a specific number. In our test server, we allocated 16 threads, but chunk generation was still slow with around 300 players.
Next, adjust your garbage collection (GC) settings. Keep in mind that GC settings allocate concurrent threads,
and you need to know the exact number. This is typically set using the -XX:ConcGCThreads=X
flag.
Don't confuse this with -XX:ParallelGCThreads=X
, as parallel GC threads run only when the
application is paused by GC and should not be considered.
After allocating threads for the tasks above, you can assign the remaining cores to tickthreads (found in the global config under threaded-regions.threads) until you reach 80% core utilization. Avoid allocating more than 80% of the cores, as plugins or the server itself may use additional threads that you can't configure or predict.
Please note that these estimates are based on player count and may not be ideal for your specific situation. You may need to fine-tune your thread allocation based on the actual usage of the threads.
To configure Folia, refer to the paper-global.yml file that you provided earlier. This file contains various settings that you can adjust to optimize Folia for your server. For more information on each setting, visit the documentation and support links found in the paper-global.yml file.
There is no more main thread. I expect every single plugin that exists to require some level of modification to function in Folia. Additionally, multithreading of any kind introduces possible race conditions in plugin held data - so, there are bound to be changes that need to be made.
So, have your expectations for compatibility at 0.
Modrinth has a filter for plugins that work on Folia as of right now.
Currently, there is a lot of API that relies on the main thread. I expect basically zero plugins that are compatible with Paper to be compatible with Folia. However, there are plans to add API that would allow Folia plugins to be compatible with Paper.
For example, the Bukkit Scheduler. The Bukkit Scheduler inherently relies on a single main thread. Folia's RegionScheduler and Folia's EntityScheduler allow scheduling of tasks to the "next tick" of whatever region "owns" either a location or an entity. These could be implemented on regular Paper, except they schedule to the main thread - in both cases, the execution of the task will occur on the thread that "owns" the location or entity. This concept applies in general, as the current Paper (single threaded) can be viewed as one giant "region" that encompasses all chunks in all worlds.
It is not yet decided whether to add this API to Paper itself directly or to Paperlib.
First, Folia breaks many plugins. To aid users in figuring out which plugins work, only plugins that have been explicitly marked by the author(s) to work with Folia will be loaded. By placing "folia-supported: true" into the plugin's plugin.yml, plugin authors can mark their plugin as compatible with regionised multithreading.
The other important rule is that the regions tick in parallel, and not concurrently. They do not share data, they do not expect to share data, and sharing of data will cause data corruption. Code that is running in one region under no circumstance can be accessing or modifying data that is in another region. Just because multithreading is in the name, it doesn't mean that everything is now thread-safe. In fact, there are only a few things that were made thread-safe to make this happen. As time goes on, the number of thread context checks will only grow, even if it comes at a performance penalty - nobody is going to use or develop for a server platform that is buggy as hell, and the only way to prevent and find these bugs is to make bad accesses fail hard at the source of the bad access.
This means that Folia compatible plugins need to take advantage of API like the RegionScheduler and the EntityScheduler to ensure their code is running on the correct thread context.
In general, it is safe to assume that a region owns chunk data in an approximate 8 chunks from the source of an event (i.e. player breaks block, can probably access 8 chunks around that block). But, this is not guaranteed - plugins should take advantage of upcoming thread-check API to ensure correct behavior.
The only guarantee of thread-safety comes from the fact that a single region owns data in certain chunks - and if that region is ticking, then it has full access to that data. This data is specifically entity/chunk/poi data, and is entirely unrelated to ANY plugin data.
Normal multithreading rules apply to data that plugins store/access their own data or another plugin's - events/commands/etc. are called in parallel because regions are ticking in parallel (we CANNOT call them in a synchronous fashion, as this opens up deadlock issues and would handicap performance). There are no easy ways out of this, it depends solely on what data is being accessed. Sometimes a concurrent collection (like ConcurrentHashMap) is enough, and often a concurrent collection used carelessly will only hide threading issues, which then become near impossible to debug.
To properly understand API additions, please read Project overview.
- RegionScheduler, AsyncScheduler, GlobalRegionScheduler, and EntityScheduler acting as a replacement for the BukkitScheduler. The entity scheduler is retrieved via Entity#getScheduler, and the rest of the schedulers can be retrieved from the Bukkit/Server classes.
- Bukkit#isOwnedByCurrentRegion to test if the current ticking region owns positions/entities
To properly understand API additions, please read Project overview.
General rules of thumb:
-
Commands for entities/players are called on the region which owns the entity/player. Console commands are executed on the global region.
-
Events involving a single entity (i.e player breaks/places block) are called 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 events fired from regions or the global region are considered synchronous, even though there is no main thread anymore.
- Most API that interacts with portals / respawning players / some player login API is broken.
- ALL scoreboard API is considered broken (this is global state that I'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 event to be completed later, on a different thread context. This is required to implement some things like spawn position select, as asynchronous chunk 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 absolutely required to prevent plugin devs from shipping code that may randomly break random parts of the server in entirely undiagnosable 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.19.4-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
Since no one wants to provide information on how to compile this, I've written this guide for WINDOWS ONLY, because I don't use linux but I'll probably make one for Windows. If you do not have GIT installed for windows you can install it from here YOU MUST HAVE GIT TO COMPILE THIS FROM THIS GUIDE
- Clone this repo, or the master repo with git via cmd
git clone Enter REPO URL HERE
- Navigate to the directory at
C:\Users\YourUsername\Folia
- Run the install.bat file to do the first part
- Run the patch.bat for the second part
- Run the jar.bat for the third part
- In the
C:\Users\YourUsername\Folia
directory open CMD and finally rungradlew createReobfBundlerJar
or gradlew createReobfBundlerJar
Your compiled jars will be in C:\Users\YourUsername\Folia\build\libs
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 found here. As such, it contains modifications to it in this project, please see the repository for license information of modified files.