Skip to content

Load island data off the main thread to fix periodic lag spikes - #18

Merged
tastybento merged 1 commit into
developfrom
fix/async-topten-refresh
Aug 27, 2026
Merged

Load island data off the main thread to fix periodic lag spikes#18
tastybento merged 1 commit into
developfrom
fix/async-topten-refresh

Conversation

@tastybento

Copy link
Copy Markdown
Member

Problem

Server admins reported periodic lag spikes (~160–970 ms, up to a 1,012 ms tick) every refresh cycle, profiled to:

TopBlockManager.refreshAll
  -> AOneBlockHook.getAllIslandData
  -> JSONDatabaseHandler.loadObjects

The refresh timer is a sync Bukkit task, and getAllIslandData() delegates to the game mode's getAllIslands(), which is a full synchronous database read (Database#loadObjects()) — it reads and deserializes every island record ever created, on the main thread, every cycle (default 5 min). The cost scales with island count and disk latency, and doubles when both AOneBlock and ChunkBlock are hooked.

Fix

refresh(hook) now runs getAllIslandData() on an async task (pure file I/O + JSON parsing — the same call Level already makes async) and hops back to the main thread only for the cheap part in the new processIslandData(): island registry lookups, player/permission checks, and swapping in the new top-ten list. Placeholder snapshots update per hook as each async load completes instead of once after a blocking refreshAll().

This moves essentially the entire refresh cost off the tick loop with no behavior change to the top ten, placeholders, or panel.

Other changes

  • CommonTestSetup stubs the scheduler to run both legs of the async→sync hop inline so the existing tests stay synchronous.
  • Bumped build.version to 2.1.1; updated CLAUDE.md to document the async/sync split.

Testing

  • mvn test — all 44 tests pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Um9roAZ8pVAqp6TZEMBjMr

The refresh task ran hook.getAllIslandData() on the main thread every
refresh cycle. In both game modes that is a full synchronous database
read (Database#loadObjects()), which deserializes every island record
ever created and was profiled at up to ~1s per cycle on large servers.

refresh(hook) now loads the island data on an async task and hops back
to the main thread only for the cheap part: island registry lookups,
player/permission checks, and swapping in the new top ten. Placeholder
snapshots update per hook as each async load lands.

Bump version to 2.1.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Um9roAZ8pVAqp6TZEMBjMr
@sonarqubecloud

Copy link
Copy Markdown

@tastybento
tastybento merged commit c527f89 into develop Aug 27, 2026
3 checks passed
@tastybento
tastybento deleted the fix/async-topten-refresh branch August 27, 2026 04:00
@tastybento tastybento mentioned this pull request Aug 27, 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.

1 participant