Fix/lmdb reopen dbi#351
Merged
Merged
Conversation
…luid ticks Two allocation/refcount hot spots in the fluid tick loop, both pure performance with no behavioural change (the serial/parallel parity test and the fluid integration suite pass unchanged): - `seed_fluid_tick` built a fresh `WorldBlockView` — cloning the `GlobalState` handle — on every call. Applying a batch of changes wakes the six fluid neighbours of every changed block, so a cascade did roughly seven `Arc` clones per changed cell. Split out `seed_fluid_tick_with_view` and build one view per batch in `apply_changes` and `seed_on_block_break`; the view reads the live chunk cache, so reusing it across the intervening writes is equivalent to rebuilding it each time. The public `seed_fluid_tick` stays as a thin wrapper for the placement/break callers. - `ChunkTickQueue::drain_due` / `drain_due_capped` allocated a fresh full-size replacement vector on every call — for every chunk with pending ticks, every game tick, even when nothing was due. Replaced with in-place `retain` compaction (order preserved, so the capped path still defers the overflow).
perf: cut per-seed state-handle clones and per-drain allocations in f…
Registry data is sourced from JSON, which cannot express NBT's distinct
numeric tags. The generic `craftflow_nbt::to_writer(&serde_json::Value)` path
serialised every JSON integer as a `Long` and every real as a `Double`. The
vanilla Java client coerces numeric tags leniently and tolerates this, but a
strict client deserialises the registry into typed structs and rejects any
field whose tag is not exactly what the schema expects — so e.g.
`dimension_type.height` (a Long here, an Int in the codec) made such clients
fail to parse the dimension registry and disconnect during login.
Encode the `dimension_type` registry through a small schema-aware converter:
integers default to `Int` (widening to `Long` only when they do not fit i32),
booleans to `Byte`, reals to `Double`, with per-field overrides for the three
fields whose vanilla tag differs — `ambient_light` (Float), `coordinate_scale`
(Double), and `fixed_time` (Long). All other registries keep the byte-for-byte
output of the previous path until they need a schema of their own.
Verified end to end: offline-mode azalea 0.14 (Minecraft 1.21.8) bots that
previously panicked on `MismatchedFieldType("DimensionTypeElement::height")`
now parse the registry and fully join, reaching the Play state and loading in.
A dev-only load-testing tool that spawns a swarm of offline-mode azalea bots to connect to a running FerrumC server and (optionally) wander, reproducing the chunk-loading, movement, and broadcast load of many simultaneous players for measuring server tick performance under real concurrency. - Standalone crate (its own `[workspace]`, listed under `exclude` in the root Cargo.toml) so azalea's large dependency tree never compiles as part of the main build, CI, or release. - Pinned to `azalea = "=0.14.0"` (Minecraft 1.21.8 / protocol 772) to match FerrumC's protocol. azalea 0.14 transitively depends on a set of pre-release RustCrypto crates whose newer published versions have incompatible APIs; the committed Cargo.lock pins the whole stack back to the working versions (documented in the README, with restore commands). - Configurable bot count, join stagger, idle vs wandering, reconnect-on-drop, and a periodic connected/peak/joins/disconnects metrics line. Transport and login are verified end to end against a local server (bots reach the server and begin the login sequence). Note: a strict client cannot yet fully join because FerrumC's registry NBT encodes some `dimension_type` fields with the wrong tag width (e.g. `height` as Long instead of Int; `ambient_light` /`coordinate_scale` as int instead of float/double). The vanilla Java client coerces these leniently; azalea deserializes into typed structs and rejects them. Making that registry data wire-conformant is a separate server-side fix.
fix: emit schema-correct NBT tags for the dimension_type registry
test: add azalea-based stress-test bot (tools/stress-bot)
Reopening an existing world failed on the first database access after a restart with `IO error: Invalid argument (os error 22)`, leaving the server unable to load any persisted save. `open_table` opened a named-database handle inside a read transaction and then dropped (aborted) that transaction before caching the handle. LMDB ties a freshly opened handle to the transaction that opened it: the handle stays private until the transaction is *committed*, and is closed automatically if the transaction is aborted. The cached handle was therefore already closed, and reusing it in a later transaction failed with `EINVAL`. The sibling `open_or_create_table` never hit this because it opens inside a write transaction that it commits, which promotes the handle into the shared environment. Newly generated worlds also worked for that reason (tables are first created through that path), which is why the failure only surfaced on the second run. Open the handle in a committed write transaction in `open_table` as well so it remains valid for the lifetime of the environment. The cost is paid once per table on first access. Adds `test_reopen_reads_existing_table`, which reinitialises a backend over an existing path and reads a previously written table — the reopen path the existing single-instance tests never exercised.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix: #a05ebe42 can not load any existed worlds