Skip to content

Async-read view for LevelChunkSection#733

Open
duranaaron wants to merge 2 commits into
Winds-Studio:ver/1.21.11from
duranaaron:ver/1.21.11
Open

Async-read view for LevelChunkSection#733
duranaaron wants to merge 2 commits into
Winds-Studio:ver/1.21.11from
duranaaron:ver/1.21.11

Conversation

@duranaaron

Copy link
Copy Markdown

Why

Plugins that read blocks off-thread currently have to call LevelChunkSection.copy() and
read through the returned wrapper. That works, but you end up with a full
LevelChunkSection including nonEmptyBlockCount / tickingBlockCount fields that go
stale as soon as a main-thread write happens, plus an object you have to keep around for
the duration of the read.

What you actually need is a stable PalettedContainer.Data reference for the block state
and biome containers, nothing else.

This adds a small API for that. LevelChunkSection.acquireAsyncReadView() returns an
AutoCloseable view backed by snapshot Data instances for both containers.

How it works

acquireAsyncSnapshot clones the current Data, publishes the clone as the new live
container, and returns the previous instance to the caller. That instance is no longer
referenced by the container and is treated as read-only.

All writes after that point, synchronised or unchecked, go to the new live instance. The
snapshot held by the caller is never mutated.

The write path is unchanged. No read counters, no copy-on-write branches, no interaction
with getAndSetUnchecked.

Benchmarks

Each acquire does one Data clone, same as LevelChunkSection.copy(). Most of the cost
in copy() already comes from BitStorage.copy() and Palette.copy(), so this does not
reduce the raw cloning cost.

The benefit is in usage. Callers no longer deal with a full LevelChunkSection that has
internally inconsistent state, and the API leaves room for improving how snapshots are
backed later without changing call sites.

Notes

  • releaseAsyncSnapshot is currently a no-op. It exists so a future implementation can
    track readers without changing the API.
  • Block counts are not exposed. They are updated outside the snapshot boundary by
    setBlockState, so any value here would be misleading.

Context

I don’t usually work on server forks, but I ran into this while building a plugin that
does a lot of off-thread block sampling. This approach worked well for that use case, so
I figured it was worth sharing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant