Commit Graph

174 Commits

Author SHA1 Message Date
Spottedleaf
7c6e2514d2 Update paper 2023-06-16 10:42:12 -07:00
Spottedleaf
0dd151fd1e Make regioniser more aggressively recalculate regions
This is to try and prevent regions from grouping together
when they really shouldn't be
2023-06-16 10:07:22 -07:00
Spottedleaf
e8e6ac4006 Avoid off-region chunk read for paper entity command
Allow usage of the specific entity command
2023-06-16 10:02:19 -07:00
Spottedleaf
dc7eeddb96 Update paper 2023-06-16 09:48:16 -07:00
Spottedleaf
fa018cc372 Update to 1.20.1
No changes to note
2023-06-13 14:24:31 -07:00
Spottedleaf
db2e6578f8 Clear main supporting position on teleport
It becomes invalid switching dimensions or by moving far. If
it used after teleporting, then it may also trip thread checks.

Fixes https://github.com/PaperMC/Folia/issues/94
2023-06-13 13:52:26 -07:00
Spottedleaf
8a067cdbdd Update leafprofiler to be able to dump to a list of strings
First steps to making this thing useful
2023-06-13 12:21:52 -07:00
Jason Penilla
23b6f9e0ef Fix processUnloads trying to unload for all regions at once 2023-06-12 13:01:23 -07:00
Spottedleaf
9b2ffd03cf Remove unused skyLightSources
Starlight does not use the sky light sources, and there
appear to be issues with TE access on Folia when initializing
them. So, we can just delete it entirely.
2023-06-10 14:10:20 -07:00
Spottedleaf
b886376c26 Update to latest paper
Make sure the player chunk loader throws when a double-remove
occurs, as that should not be happening on Folia
2023-06-10 14:09:11 -07:00
Spottedleaf
fd838ffbee Update to latest paper
Fix two regionizer issues:

In ThreadedRegionizer#addChunk, fix the incorrect handling
of merging two regions where one of the regions had
pending merges. If the first region had pending merges,
and the second was marked as "ready" then the merge would
cause a "ready" region to have pending merges. The fix is
to simply downgrade the "ready" region to "transient,"
as was previously done if the merge was delayed in the
case where the first region was "ticking."

Additionally, prevent the creation of empty regions
by checking if any new sections were created. This would
happen when a section existed, but had no marked chunks
in it AND all of the sections neighbours existed. In these
cases, no region needs to be created as no sections were
created.
2023-06-09 23:44:24 -07:00
Spottedleaf
d0517f1656 Fix compile / boot 2023-06-08 21:03:13 -07:00
Spottedleaf
1b0a5071d0 Initial patch apply 2023-06-08 20:15:55 -07:00
Spottedleaf
bf7ba50dcd Fix missing captureBlockStates usage
Needs to be redirected to the regionized world data.
2023-06-07 16:37:19 -07:00
Spottedleaf
308d1ca5dc Update to latest paper 1.19 2023-06-07 15:32:55 -07:00
Spottedleaf
ca3b7adee2 Resolve issues with player autosave
The last save was based on region tick, but it was not adjusted
on player region change or region merge. To resolve this,
I have adjusted the last save to be based on time so that it does
not need adjustments on region change or region merge.

Additionally, fix the max per tick handling.
2023-05-27 12:14:57 -07:00
Spottedleaf
df0065bd53 Eliminate usages of MinecraftServer#tickCount field
Mobs would use the evenness of server tick count plus id
to determine whether they eoilf tick only their running
goals or to tick the goal selector to find additional
goals. If the server had an even number of regions,
then every 50ms the server tick field would be incremented
by an even number and as a result would not change
the evenness of the mob goal check. This could put
some mobs in a state where they only ticked their
running goals, which would result in them
freezing.

Fixes https://github.com/PaperMC/Folia/issues/42
2023-05-27 09:41:57 -07:00
WillQi
be3c9e596e Fix off region raid heroes 2023-05-16 15:39:40 -07:00
Spottedleaf
f15f1ceab5 Fix some bugs in ThreadedTicketLevelPropagator
First, when a section update is stolen, the thread that acquires
the stolen update should remove the update from the update queue
before returning to mark it as completed and allow other threads
waiting on the update to continue. This fixes a deadlock issue
with section updates.

Fix incorrect decrease queue resize. Previously, it attempted
to resize the _increase_ queue, which is the wrong queue.

Use ALL_DIRECTIONS_BITSET for every decrease queue direction bitset
as decrease propagation cancellation due to neighbour values exceeding
the target decrease value cause some neighbour directions to not
be checked, which causes the final update grid to be incorrect.
2023-05-15 21:29:38 -07:00
Spottedleaf
ed61eb315e Fix infinite loop in ChunkBasedPriorityTask#queue
We must attempt to synchronise when the returned queue is null
so that we can get a correct queue result or return false due to
the reference counter being released, or even to throw an exception
when the queue is null but the reference counter is not released.
2023-05-15 20:46:30 -07:00
Spottedleaf
1128810029 Always recalculate light list on protochunk deserialize
I noticed during my stress testing that the total size of the
light list was far too large, which indicates many duplicates.
For me, this caused many GC problems which made stress testing
harder.

It turns out, it was possible for the light list recalculation
logic to occur _and_ the addition of the light list data from
the NBT data. Since there is no logic to de-duplicate this list,
every chunk load would re-add all light sources into the light
list and the light list would grow uncontrollably.

Since the recalculation logic would often run, I have
decided to solve this by discarding the data on disk and always
just calculating the list from the chunk data alone. Additionally,
I have applied an optimization from Vanilla 1.20 to avoid
searching sections without light sources by first checking the
palette for possible block sources.

Now my stress tests do not have issues with GC at all.
2023-05-15 20:37:29 -07:00
Spottedleaf
94b1400a81 Optimise recalcBlockCounts() for empty sections
In 1.18, every chunk section is initialised to a non-null value
and recalcBlockCounts() is invoked for each section.
However, in a standard world, most sections are empty. In such cases,
recalcBlockCounts() would iterate over ever position - even though
the block data would all be air. To avoid this, we skip
searching the section unless the palette indicates there _could_ be
a non-air block state or non-empty fluid state.

Chunk loading initially showed that recalcBlockCounts() over
sections with a ZeroBitStorage data to to take ~20% of the process,
now it takes <1%.
2023-05-15 20:30:16 -07:00
Spottedleaf
22085eae15 Properly cancel chunk load tasks that were not scheduled
Since the chunk load task was not scheduled, the entity/poi load
task fields will not be set, but the task complete counter
will not be adjusted. Thus, the chunk load task will not complete.

To resolve this, detect when the entity/poi tasks were not scheduled
and decrement the task complete counter in such cases.
2023-05-15 12:27:19 -07:00
Spottedleaf
7595ff6bb2 Mark POI/Entity load tasks as completed before releasing scheduling lock
It must be marked as completed during that lock hold since the
waiters field is set to null. Thus, any other thread attempting
a cancellation will fail to remove from waiters. Also, any
other thread attempting to cancel may set the completed field
to true which would cause accept() to fail as well.

Completion was always designed to happen while holding the
scheduling lock to prevent these race conditions. The code
was originally set up to complete while not holding the
scheduling lock to avoid invoking callbacks while holding the
lock, however the access to the completion field was not
considered.

Resolve this by marking the callback as completed during the
lock, but invoking the accept() function after releasing
the lock. This will prevent any cancellation attempts to be
blocked, and allow the current thread to complete the callback
without any issues.
2023-05-15 11:42:31 -07:00
Spottedleaf
80af54eeda Synchronize PaperPermissionManager
Since multiple regions can exist, there are concurrent accesses
in this class. To prevent deadlock, the monitor is not held
when recalculating permissions, as Permissable holds its own
lock.

This fixes CMEs originating from this class.
2023-05-15 11:00:49 -07:00
Spottedleaf
051ec0dd65 Fix concurrenct access to lookups field in RegistryOps
The concurrent access occurs on the Netty IO threads when
serializing packets. Thus, it seems it was an oversight of
the implementator of this function as there are typically
more than one Netty IO thread.

Fixes https://github.com/PaperMC/Folia/issues/11
2023-05-15 00:26:56 -07:00
Spottedleaf
31b5b1575b Use coordinate-based locking to increase chunk system parallelism
A significant overhead in Folia comes from the chunk system's
locks, the ticket lock and the scheduling lock. The public
test server, which had ~330 players, had signficant performance
problems with these locks: ~80% of the time spent ticking
was _waiting_ for the locks to free. Given that it used
around 15 cores total at peak, this is a complete and utter loss
of potential.

To address this issue, I have replaced the ticket lock and scheduling
lock with two ReentrantAreaLocks. The ReentrantAreaLock takes a
shift, which is used internally to group positions into sections.
This grouping is neccessary, as the possible radius of area that
needs to be acquired for any given lock usage is up to 64. As such,
the shift is critical to reduce the number of areas required to lock
for any lock operation. Currently, it is set to a shift of 6, which
is identical to the ticket level propagation shift (and, it must be
at least the ticket level propagation shift AND the region shift).

The chunk system locking changes required a complete rewrite of the
chunk system tick, chunk system unload, and chunk system ticket level
propagation - as all of the previous logic only works with a single
global lock.

This does introduce two other section shifts: the lock shift, and the
ticket shift. The lock shift is simply what shift the area locks use,
and the ticket shift represents the size of the ticket sections.
Currently, these values are just set to the region shift for simplicity.
However, they are not arbitrary: the lock shift must be at least the size
of the ticket shift and must be at least the size of the region shift.
The ticket shift must also be >= the ceil(log2(max ticket level source)).

The chunk system's ticket propagator is now global state, instead of
region state. This cleans up the logic for ticket levels significantly,
and removes usage of the region lock in this area, but it also means
that the addition of a ticket no longer creates a region. To alleviate
the side effects of this change, the global tick thread now processes
ticket level updates for each world every tick to guarantee eventual
ticket level processing. The chunk system also provides a hook to
process ticket level changes in a given _section_, so that the
region queue can guarantee that after adding its reference counter
that the region section is created/exists/wont be destroyed.

The ticket propagator operates by updating the sources in a single ticket
section, and propagating the updates to its 1 radius neighbours. This
allows the ticket updates to occur in parallel or selectively (see above).
Currently, the process ticket level update function operates by
polling from a concurrent queue of sections to update and simply
invoking the single section update logic. This allows the function
to operate completely in parallel, provided the queue is ordered right.
Additionally, this limits the area used in the ticket/scheduling lock
when processing updates, which should massively increase parallelism compared
to before.

The chunk system ticket addition for expirable ticket types has been modified
to no longer track exact tick deadlines, as this relies on what region the
ticket is in. Instead, the chunk system tracks a map of
lock section -> (chunk coordinate -> expire ticket count) and every ticket
has been changed to have a removeDelay count that is decremented each tick.
Each region searches its own sections to find tickets to try to expire.

Chunk system unloading has been modified to track unloads by lock section.
The ordering is determined by which section a chunk resides in.
The unload process now removes from unload sections and processes
the full unload stages (1, 2, 3) before moving to the next section, if possible.
This allows the unload logic to only hold one lock section at a time for
each lock, which is a massive parallelism increase.

In stress testing, these changes lowered the locking overhead to only 5%
from ~70%, which completely fix the original problem as described.
2023-05-14 19:46:24 -07:00
Jason
9bd857dabc
Undo making JavaPlugin#logger field public (see PaperMC/Paper#9125) (#76) 2023-05-14 18:10:49 -07:00
Spottedleaf
10a11c3712 Do not access POI data for lodestone compass
Instead, we can just check the loaded chunk's block position for
the lodestone block, as that is at least safe enough for the light
engine compared to the POI access. This should make it safe for
off-region access.

Fixes https://github.com/PaperMC/Folia/issues/60
2023-05-13 17:30:55 -07:00
Spottedleaf
47105ea28e Break redstone on top of trap doors early
This logic hooks into the neighbour update which should be invoked
as a result of redstone powering the trap door.
2023-05-01 18:28:54 -07:00
Spottedleaf
b97116b7b2 Skip worldstate access when waking players up during data deserialization
In general, worldstate read/write is unacceptable during
data deserialization and is racey even in Vanilla. But in Folia,
some accesses may throw and as such we need to fix this directly.

Fixes https://github.com/PaperMC/Folia/issues/57
2023-04-23 07:50:43 -07:00
Spottedleaf
3a95485043 Block reading in-world tile entities on worldgen threads
The returned TE may be in the world, in which case it is unsafe
for the current thread to modify or access its contents.

Fixes https://github.com/PaperMC/Folia/issues/52
2023-04-23 07:50:42 -07:00
Spottedleaf
dddaab9bbd Prevent block updates in non-loaded or non-owned chunks
This is to prevent block physics from tripping thread checks by
far exceeding the bounds of the current region. While this does
add explicit block update suppression techniques, it's better
than the server crashing.
2023-04-17 19:51:21 -07:00
Spottedleaf
ce49776448 Add more debugging information to chunk sending
Perform thread checks on the chunk send and warn when the
world is mismatched. I suspect that the world mismatches for
an unknown reason, but need to confirm it to chase it down.
2023-04-17 15:37:16 -07:00
Spottedleaf
25e0cbdae4 Rework some parts of the player chunk loader
Change overview:
- Rework limiting
- Remove mid tick updates
- Introduce consistency checks

The old limiting logic used an intervalled counter, but
did not account for possible slight changes in mid tick
invoke rate as it relied heavily on mid-tick logic. Due to
the removal of mid tick updates, it is now important that
the logic functions correctly no matter what rate it is invoked
at. The new logic directly tracks the last update time and
allocates an amount based proportional on the rate targetted,
which makes the logic call rate independent.

The removal of mid tick updates is done to eliminate recursive
call risk, and to additionally reduce the lock pressure on the
chunk system by grouping chunk loads onto one part of the tick
rather than spreading it out. The limiting rework should ensure
that this does not negatively affect rates, but it will decrease
the perceived smoothness of chunk generation/loading at low rates.

Introduce more consistency checks such as correct tick thread
and ticking-after-removal checks. Also, perform checks during the player
chunk loader tick to avoid updating potentially removed
players during the tick.
The checks are primarily made to try to hunt down a bug that
is causing the player chunk loader to double send a chunk
to a player.
2023-04-10 17:51:21 -07:00
Spottedleaf
ad70ddfc20 Lag compensate block breaking
Due to TPS catchup being removed, a lost tick will always
affect block breaking.

Additionally, constant low TPS would affect block breaking
in an intrusive manner to the user when there is no need
for that to occur.
2023-04-10 14:16:16 -07:00
Spottedleaf
105f6d6a21 Adjust CB async teleport dismount behavior
The expected behavior is that the entity is only dismounted
_if_ the teleport takes place, not regardless of whether
the teleport takes place.

To adhere to the expected behavior, we need to create a new teleport
flag so that the NMS teleportAsync can perform the dismount.
2023-04-08 19:16:10 -07:00
Spottedleaf
c9ded2de1c Add entity/player/chunk counters to /tps
Required to add some basic hacks to expose a regionstats object
in the TickRegions data class, but this ensures that the retrieval
is thread-safe and could possibly support other data exposure
for async reads.

Additionally, since DecimalFormat is not thread-safe we need
to use ThreadLocals to instantiate them. Change the format
as well to use commas to separate groups of digits when
formatting large numbers so they are easier to read.
For example, 1000 becomes 1,000.
2023-04-08 18:44:37 -07:00
Spottedleaf
4431a66c12 Make CB Entity async teleport dismount entities being teleported
This preserves behavior with the older API that did
dismount the entity before teleporting

Fixes https://github.com/PaperMC/Folia/issues/36
2023-04-08 16:56:30 -07:00
Spottedleaf
d34fb878bb Always send untrack chunk packets
Vanilla inserted the alive check so that dead players
could see the chunks around them, but in Folia we do not
remove dead players so chunks will still load for them.

This prevents the client from having chunks in memory it
should not.
2023-04-03 22:50:00 -07:00
Spottedleaf
774141dfb1 Fix mob entity inventory loss when switching dimensions
The inventory was being cleared by removing the entity
from the world, but Folia changed the remove to be
before the entity copy which caused the new entity
to have a cleared inventory. Fix this by creating
a post-dimension copy callback that will clear
the inventory of the old entity.

Fixes https://github.com/PaperMC/Folia/issues/29
2023-04-03 22:14:42 -07:00
Spottedleaf
445613b931 Note world as well when a region fails to tick or execute tasks
Should always include the world if we're including the center
position
2023-04-03 21:26:19 -07:00
Spottedleaf
f8a17538e6 Fix destroying beehive without any players nearby throwing an exception
If the player moves out of range by the time the block is destroyed,
then the exception would throw and remove the player from the world

Additionally, when players fail to tick instead of removing
the player from the world, kick them to prevent a limbo state
2023-04-03 21:26:16 -07:00
Spottedleaf
4b0c614847 Calculate correct redstone offset when merging regions
It should be offset = to - from, not from - to. This should
fix redstone freezing randomly when merging regions.

Fixes https://github.com/PaperMC/Folia/issues/35
2023-04-03 19:33:42 -07:00
Spottedleaf
6d18e8e9b6 Make uses of SimpleDateFormat thread-safe
Turns out, the utility is not thread-safe to use for whatever
reason. So, we need to use ThreadLocal to create instances
per thread.
2023-04-03 18:41:09 -07:00
Spottedleaf
33d2aa8cf7 Make sign update executor use the EntityScheduler
The MinecraftServer executor will throw, and thanks
to CompletableFuture's awful exception handling
the exception was not logged or handled. Add
exception handling as well.

Fixes https://github.com/PaperMC/Folia/issues/27
2023-04-01 07:24:36 -07:00
Spottedleaf
7072994557 Acquire scheduling lock in NewChunkHolder#onFullChunkLoadChange
It modifies data that should be held by the lock: pending
chunk status
2023-04-01 00:53:27 -07:00
Spottedleaf
700d3c580c Always process specialCaseUnload during ticket level updates
It is not guaranteed that ticket levels are updated, so we need to
to move the logic so that it always runs whether or not tickets
update.
2023-03-31 21:20:53 -07:00
Spottedleaf
76b06a1260 Do not call getGameTime when portalling Villagers
The code to stop all brain tasks is required to pass the current
game time to the tasks it stops. But, when a villager is being
portalled, the copied entity does not have any running tasks. So,
we can simply return early before invoking getGameTime if there
are no running tasks.

Fixes https://github.com/PaperMC/Folia/issues/23
2023-03-31 20:48:20 -07:00
Spottedleaf
3f377072d8 Make move event location update use teleportAsync
Additionally, make the teleportAsync call immediately teleport
if the current caller owns the entity.

Fixes https://github.com/PaperMC/Folia/issues/18
2023-03-31 19:13:19 -07:00