With ConcurrentUtil 0.0.2, we can make all thread pools
(worker+I/O) have their thread counts configurable on the fly.
The new I/O system splits the compression/decompression work
from the I/O. The compression/decompression is ran on the worker
pool, while the I/O is ran on the I/O pool. This allows for
better cpu utilisation control on systems with low core counts,
and allows higher read/write speeds on systems with higher
core counts.
Additionally, the I/O scheduling for thread counts > 1 is also
improved as it longer selects a thread to schedule based on the
chunk location.
The rDNS is not cheap and is not necessary. We skip the
rDNS by providing the input address as the host name when
the input address is a plain ipv4/ipv6 address.
The basic problem with the chunk tick iteration is that
Vanilla will iterate over all chunk holders to find ticking chunks.
However, there are usually many more chunk holders than
ticking chunks. We can eliminate the cost of finding the
ticking chunks by maintaining our own list of ticking chunks.
We don't need to check for this with the chunk system, as
ticking chunks are actually guaranteed to ticking. Additionally,
ticking chunks may only become non-ticking during the chunk holder
manager tick - which will not happen during chunk ticking.
It may be possible to invoke moonrise$getRawPalette before
the palette's single value is initialised, so we need to track
the returned raw palette array.
1. Need a better solution for EntityMixin block/fire collision
2. Fixed inconsistent Vanilla behavior for ExplosionMixin
Mostly revolved around the explosion intensity calculator,
as well as the damage calculator
3. Optimise ExplosionMixin to not call getSeenPercent twice,
which is a new "feature" of 1.21
4. Optimise VoxelShapeMixin#toAabbsUncached()
The regular forAllBoxes method on VoxelShape will incur
indirection costs due to the virtual method invoke on
the coordinate retrieval as well as on the consumer itself
If the server tick length is high, then the amount of time
available to process chunk tasks inbetween ticks is low. As a
result, chunk loading and generation may appear to slow down.
To ensure that chunk tasks are always processed, we add logic to
execute chunk tasks during tile entity tick, entity tick, chunk
random ticking, and scheduled block/fluid ticking. The mid-tick task
execution is timed so that it is not prioritised over the server
tick.
To ensure that a single world does not eat up allocated
processing time for tasks, execute tasks for all worlds
before returning from pollTaskInternal().
While the null UUID is almost certainly an error, the old
implementation did not NPE as it used a plain HashMap for lookup
by UUID, whereas we use a ConcurrentHashMap which will NPE on
null keys.
The unload queue stored the chunks in the same section as
the chunk coordinate, when it needed to apply the unload shift.
Additionally, change the default region shift to the ticket
propagator shift as there is no benefit to using a low region
shift since no regionizing is occuring. This makes the unload
queue shift 6, which should reduce the number of sections to deal
with while processing unloads.
They should be less fragile for breakages.
Additionally, modify PoiManagerMixin to work around an issue where
our getOrCreate() method is not being invoked _because_ its return
type was PoiSection and not Object. Apparently, the JVM will search
the superclass when a direct match (params+return type) is not found.
The full chunk map should mirror immediately the
full chunk status, so it should be added immediately after
upgrading to FULL or removed immediately before downgrading to
INACCESSIBLE.
Implementations for ChunkStatuses below FULL are supposed to always
return ProtoChunk instances. However, since we used the last completed
status, it could return LevelChunk.
To resolve this, follow Vanilla behavior of tracking chunk
completions by status and replace old ProtoChunk statuses with
ImposterProtoChunk when the chunk generates to FULL.
Additionally, implement an optimisation for retrieving full chunks
by storing a map of pos -> LevelChunk. This requires only a simple
map lookup to occur for full chunks which are loaded.
This allows us to have safe off-thread reads, as we can guarantee
that the palette is associated with the data (which is why
a Data container is used in the first place).