Skip to content

perf(core): bucket and index timeline projections - #1722

Open
hmans wants to merge 5 commits into
mainfrom
hmans/ram-bucket-projections
Open

perf(core): bucket and index timeline projections#1722
hmans wants to merge 5 commits into
mainfrom
hmans/ram-bucket-projections

Conversation

@hmans

@hmans hmans commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Why

Room Timeline retained decoded protobuf payloads and string-heavy metadata for
every room and every point in history. Threads independently duplicated many of
the same stable IDs in maps and summaries. Their RAM cost therefore grew with
the complete retained message history.

Closes #1721.

What changed

  • Partition Room Timeline payloads into fixed per-room UTC-week buckets while
    preserving its one ordered EVT consumer and lightweight global indexes.
  • Keep a configurable recent window decoded in RAM
    (core.room_timeline_hot_window /
    CHATTO_CORE_ROOM_TIMELINE_HOT_WINDOW, default 30d).
  • Reconstruct cold buckets from exact EVT sequence references with 16 bounded
    direct reads, atomic installation, shared concurrent success/failure results,
    and context-aware errors.
  • Select paginated thread references before hydration so opening one page of a
    long-lived thread does not load its complete history.
  • Intern stable event, room, and user IDs once per projection, then represent
    timeline rows, posting lists, body state, echo/attachment indexes, thread
    mappings, summaries, participants, and follows with 32-bit handles, dense
    slices, and packed flags.
  • Keep Room Timeline and Threads handle spaces independent, so replay,
    readiness, snapshots, and failure remain independently owned.
  • Store only stable IDs and sequences at snapshot boundaries. Restore rebuilds
    process-local handles, with canonical stable-ID ordering and byte-identical
    round-trip coverage.
  • Add operator diagnostics, retained-heap benchmarks, cold-load/race/snapshot
    tests, ADR-056, architecture/FDR updates, and operator configuration docs.

Results

  • The deterministic 50k-message benchmark drops cold Room Timeline from 1,251
    to 276 retained heap bytes/message across the full PR (77.9%).
  • Compared with the already-bucketed branch, compact indexing drops cold Room
    Timeline from 432.2 to 276.0 bytes/message (36.1%), Threads from 311.3 to
    118.1 bytes/message (62.1%), and their combined retained metadata from 743.5
    to 394.1 bytes/message (47.0%).
  • A snapshot-disabled cold boot against the imported production-derived
    53,763-event history replayed Room Timeline in 1.14 seconds and Threads in
    1.14 seconds.
  • On that same history, whole Go heap after forced GC fell from 45.14 MB on the
    already-bucketed branch to 34.66 MB with compact indexes (23.2%). The
    projection-specific diagnostics were also corrected to account for compact
    slice capacity instead of charging map overhead per element.
  • Historical buckets remain resident after their first read in this version.
    Access timestamps and resident-byte accounting prepare a later bounded LRU.

Compatibility and rollout

  • No public API, realtime protocol, or persisted EVT contract changes.
  • The bucketed Room Timeline snapshot uses its schema-fingerprinted v2
    contract. The indexed representation preserves that stable protobuf shape;
    handles never cross the snapshot boundary.
  • Threads preserves its existing v1 snapshot contract and likewise rebuilds
    its independent handles during restore.
  • Pre-bucketing Room Timeline snapshots use a different contract fingerprint
    and safely cold-replay EVT once. Rolling back uses the old binary's
    independent contract namespace.
  • Privacy boundaries are rechecked after lazy loads, so a concurrent
    retraction or user-key shred cannot reintroduce or return deleted content.

Test plan

  • mise codegen-proto
  • targeted Room Timeline, Thread, handle-table, and snapshot tests
  • targeted race tests for cold hydration, snapshots, and adversarial
    handle-order restore
  • repeated byte-identical snapshot round trips
  • mise test-cli
  • mise lint
  • mise license-check
  • architecture-inventory source-link and paragraph-length validation
  • snapshot-disabled replay and forced-GC measurement against 53,763 retained
    production-derived EVT messages
  • deterministic retained-heap benchmark at 50,000 logical messages / 124,478
    events
  • adversarial code-review loop; both findings fixed, no remaining findings

@hmans hmans changed the title feat(core): bucket room timeline payloads perf(core): bucket and index timeline projections Jul 24, 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.

Bucket Room Timeline projection history to bound resident RAM

1 participant