Skip to content

Reuse ChunkMeshWorker update scratch storage - #5391

Closed
skrcode wants to merge 2 commits into
MovingBlocks:soloturn-chunk-mesh-worker-sortfrom
skrcode:jaipilot/pr-1-bxwA2HNehZxD
Closed

skrcode wants to merge 2 commits into
MovingBlocks:soloturn-chunk-mesh-worker-sortfrom
skrcode:jaipilot/pr-1-bxwA2HNehZxD

Conversation

@skrcode

@skrcode skrcode commented Aug 23, 2026

Copy link
Copy Markdown

This is a one-commit JAIPilot Cloud follow-up on the exact current head of MovingBlocks/Terasology#5367. It targets that PR branch directly.

Change

Reuse a private per-worker ArrayList for the ready-and-dirty chunk set instead of allocating a new list every rendered frame. A finally block clears the scratch list on both normal and exceptional exits.

Proof

  • Exact parent: a7a9c63, the current perf(rendering): sort only the chunks being queued for meshing #5367 head.
  • The sole update call path is owned by the render/main thread; filtering, order, dirty re-checks, emission, and return count are unchanged.
  • The same eight focused ChunkMeshWorker tests passed before and after.
  • At MEGA view distance with 7,623 chunks and about 5 percent dirty, five fixed allocation observations moved from 9,863.97 to 3,127.97 bytes per update, about 68 percent lower.
  • The affected engine build, Checkstyle, PMD, and SpotBugs completed with no new findings.

Boundary and disclosure

The session did not complete the entire engine-tests suite, so this claims only the focused tests and affected-module gates. The unchanged comparator remains the dominant allocator. The measurement uses synthetic DummyChunks and is an allocation-count proof, not an end-to-end frame-rate claim.

JAIPilot Cloud generated and validated the patch in skrcode/Terasology#2. I reviewed the exact ancestry, complete one-file diff, call-path ownership evidence, and verification boundary before offering it here.

soloturn and others added 2 commits August 18, 2026 21:41
ChunkMeshWorker.update() sorted the whole proximity list front-to-back and
then filtered while walking it, so it ordered thousands of chunks to decide
the order of the handful dirty that frame. Filtering first and sorting only
those gives the same sequence - ordering and filtering commute here.

update() runs once per frame, from RenderableWorldImpl's first rendering
stage. Measured on a reproduction of the list and comparator, at the MEGA
view distance of 33x7x33 = 7623 chunks:

  sort-all, list nearly sorted from last frame:  ~200us/frame
  filter-then-sort:                               ~27us/frame

roughly 7x, or ~0.2ms of a 16.7ms frame. The nearly-sorted row is the
honest one - a frame re-sorts what it sorted last frame, perturbed only by
camera drift, which TimSort handles in about O(n); on a shuffled list the
same measurement is ~1.2ms. Either way the cost did not move when the dirty
count went from 5 to 50, which is the tell that it was all in touching the
list rather than in the queueing.

The comparator is not cheap per call: it re-reads the camera through a
Provider and, via Chunk.getRenderPosition(), allocates two Vector3f per
comparison. So this is really about calling it O(dirty log dirty) times
instead of O(n log n).

isDirty() is still re-checked immediately before each emit rather than only
when the list is built. Emitting can drive mesh generation synchronously,
which clears the flag, and add() does not deduplicate - so a chunk present
in the proximity list more than once would otherwise be queued again for a
mesh the emission before it just produced. ChunkMeshWorkerTest's
testChunkIsNotProcessedTwice covers exactly that and caught it.

Measured with a throwaway reproduction rather than the real classes: 7623
real ChunkImpls is about a gigabyte, since each carries a dense 16-bit block
array. The comparator stand-in used one indirection for the camera where the
real one uses two, so the figures understate rather than flatter.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1cdee5d1-528a-4018-ae76-f913d73ea634

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@soloturn
soloturn force-pushed the soloturn-chunk-mesh-worker-sort branch from 8990896 to 05f2fd4 Compare August 27, 2026 19:30
soloturn added a commit that referenced this pull request Aug 27, 2026
From skrcode's PR #5391 review comment (9863 -> 3128 bytes/update measured).
Single-threaded, one call per frame - safe to reuse. Cleared in finally.

Co-Authored-By: soloturn <soloturn@gmail.com>
@skrcode

skrcode commented Aug 28, 2026

Copy link
Copy Markdown
Author

Closing as superseded: the scratch-list reuse from this companion was incorporated into #5367 as commit 3786379. Thanks @soloturn for folding it into the original change.

@skrcode skrcode closed this Aug 28, 2026
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.

2 participants