Repository navigation
Description
id(world): admin_history_bytes re-serializes the entire retained admin history on every accepted event — track retained bytes incrementally
Scope: PR #3998 head 47937fe3e73707eaefbaddc6d196a45f26ddc366 (fix(id): export host events through authorized journal history). The admin-history machinery does not exist on main yet — it is introduced by that PR — so this is a follow-up on the PR's new code, cross-linked both ways. Independent origin: Codex P2 review comment r4437438581 on PR #3998; re-verified line-by-line against the PR head this run, and left unfiled by the 2026-11-02 pr-comment-review run only because that run hit its per-repo filing cap.
Evidence (all line numbers on PR head 47937fe3)
-
pkgs/id/src/world/core.rs:7-12— the helper itself:fn admin_history_bytes<'a>(events: impl IntoIterator<Item = &'a WorldEvent>) -> usize { events .into_iter() .map(|event| serde_json::to_vec(event).map_or(usize::MAX, |bytes| bytes.len())) .fold(0usize, usize::saturating_add) }
Every call allocates and JSON-serializes every event it is given, just to sum the byte lengths.
-
pkgs/id/src/world/core.rs:1317-1336—record_admin_historypushes the new event, then evaluates the helper in the trim-loop condition:while self.admin_history.len() > self.limits.retained_events.min(MAX_ADMIN_HISTORY_EVENTS) || admin_history_bytes(&self.admin_history) > MAX_ADMIN_HISTORY_BYTES
In steady state (length within cap) the byte total is computed on every call, and each
pop_frontre-evaluates the condition — so trimming k events costs k+1 full re-serializations of the remaining deque. -
Call frequency:
record_admin_historyruns on the accept path —pkgs/id/src/world/core.rs:1312(inside event acceptance), alsocore.rs:457,core.rs:650, andpkgs/id/src/world/actor.rs:445. Every accepted input, chat message, or host event pays the full scan even when no admin export is ever requested. -
Bounds:
pkgs/id/src/world/mod.rs:57MAX_ADMIN_HISTORY_EVENTS = 4096;mod.rs:59MAX_ADMIN_HISTORY_BYTES = 64 MiB. With the default 1,024-event retention and valid 16 KiB inputs, one accepted event can re-encode ~16 MiB of JSON; at the 4,096-event cap, up to the full 64 MiB byte budget is re-encoded per event. -
Secondary edge in the same helper: a single event whose serialization fails counts as
usize::MAX, so the total saturates and the trim loop would drain the entire retained history one pop (and one full re-scan) at a time. -
WorldCoreis deliberately serialized:core.rs:28— "Keep it behind one actor/mutex so event sequencing is serialized." The re-serialization is synchronous work inside that single world actor, so it delays subsequent inputs, ticks, and view requests for everyone in the world. -
One legitimate one-shot use exists:
restore_admin_history(core.rs:1349) validates a checkpoint's history once at restore time. That call can stay, or reuse the same cached sizes.
Why it matters
This is an O(retained-history) tax on the hottest path in the world actor, paid per accepted event, forever, in exchange for a byte total that changes by exactly one event's size per call. Busy worlds (the ones that accumulate a large retained history) get slower per event the more history they retain — precisely backwards. The fix is mechanical and local: cache each event's encoded size when it enters the deque and maintain a running total as events enter and leave.
Acceptance criteria
-
record_admin_historyis O(1) in the retained-history size per accepted event (amortized): encoded sizes are cached per retained event and a running byte total is maintained incrementally on push/pop; no per-event full re-serialization on the accept path. - Trim behavior is unchanged: the same events are retained/evicted under both the event-count cap (
retained_events.min(MAX_ADMIN_HISTORY_EVENTS)) and the byte cap (MAX_ADMIN_HISTORY_BYTES), andadmin_history_completeflips exactly as before. -
restore_admin_history's byte-bound validation still rejects an over-budget checkpoint history (it may reuse the cached sizes or keep the one-shot scan — restore is not the hot path). - The serialization-error edge is handled deliberately (an event that cannot be serialized cannot silently poison the running total or drain the whole history); the chosen behavior is pinned by a test.
- A regression test or benchmark demonstrates the improvement (e.g. a test with a large retained history asserting the trim outcome, plus a comment/measurement showing per-event cost no longer scales with history size), and the existing
worldtest suite passes.
Cross-links: PR #3998 (introduces the code), Codex review comment r4437438581.
Activity
dezren39 commentedon Nov 2, 2026
🤖 Agent note · filed
new-issue-creator-code-a)new-issue-creator-code-a, run 2026-11-02 16:35 CST (2026-11-02T22:35Z)admin_history_bytes(PR fix(id): export host events through authorized journal history #3998 head47937fe3) re-serializes the entire retained admin history on every accepted event; track retained bytes incrementally instead. Origin: Codex P2r4437438581on PR fix(id): export host events through authorized journal history #3998, left unfiled by pr-comment-review's per-repo cap; re-verified line-by-line on the PR head this run (helper atpkgs/id/src/world/core.rs:7-12, trim loop:1328-1329, accept-path callerscore.rs:1312/actor.rs:445, capsmod.rs:57,59). Cross-linked on PR fix(id): export host events through authorized journal history #3998.dezren39 commentedon Nov 2, 2026
🤖 Agent note · picked up
admin_history_byteshot-path finding at current PR fix(id): export host events through authorized journal history #3998 head and route the narrow fix; no changes to Drew-owned PR fix(id): export host events through authorized journal history #3998.40 remaining items
dezren39 commentedon Nov 3, 2026
🤖 Agent note · parked
dezren39 commentedon Nov 3, 2026
🤖 Agent note · picked up
dezren39 commentedon Nov 3, 2026
🤖 Agent note · picked up
~/git/fleet/6562-4633-admin-historyon branchqueue/6562-4633-admin-history-bytes, which already holds an uncommitted incremental byte-ledger implementation inpkgs/id/src/world/core.rs; verifying it, adding regression coverage, and opening the PR.admin_history_bytesaccounting, trim/restore semantics preserved, targeted world tests passing.queue/6562-4633-admin-history-bytes; gated on PR fix(id): export host events through authorized journal history #3998 (now merged)Merge pull request #4747 from developing-today/queue/6562-4633-admin-…
dezren39 commentedon Nov 3, 2026
🤖 Agent note · done
AdminHistoryByteLedgercaches each retained event's encoded size and maintains the total on push/pop, sorecord_admin_historyno longer re-serializes the retained history per accepted event. Unserializable events count asusize::MAX(legacy rescan semantics, forces a trim); restore keeps its one-shot over-budget rejection and rebuilds the ledger.cargo test --manifest-path pkgs/id/Cargo.toml worldon the laptop: 479 passed, 0 failed, including 4 new ledger regression tests (unserializable-as-MAX, count-trim sync, byte-cap trim, restore sync). Codex review on PR fix(id/world): track retained admin-history bytes incrementally (#4633) #4747 completed with no findings.queue/6562-4633-admin-history-bytes· commit e9eae6cdezren39 commentedon Nov 3, 2026
🤖 Agent note · done (correction to the test evidence in the previous note)
cargo test --manifest-path pkgs/id/Cargo.toml worldwas wrong: two concurrent runs of that command raced in the shared laptop target dir, and the run whose output I used did not cover the lib binary, while the other aborted. Corrected, sequentially verified evidence for PR fix(id/world): track retained admin-history bytes incrementally (#4633) #4747:world::testsmodule (the changed code's tests): 160 passed, 0 failed, including the 4 newadmin_history_byte_ledgertests (each also verified by name).worldfilter cannot complete on the laptop: three CLI-args tests stack-overflow and abort the lib binary —cli::tests::module_trust_keys_are_repeatable_and_require_world_mode,cli::tests::test_cli_parse_world_new_and_stats,cli::world_limits_args_tests::flag_defaults_match_the_built_in_limits. Proven pre-existing on clean pre-merge main d05c22e (first parent of the PR fix(id/world): track retained admin-history bytes incrementally (#4633) #4747 merge), unrelated to this change; filed as id(cli): module_trust_keys_are_repeatable_and_require_world_mode stack-overflows, aborting the pkgs/id lib test binary #4751.