Skip to content

perf(status): ~4s on remote store is get_records pulling every full live doc to drift-hash — parallelize + fingerprint (follow-up to #28/#31) #34

Description

@AusafG5

Follow-up to #28 + #31 (both shipped, thank you). Re-profiled /api/state on 0.4.4 against a remote store and traced the real residual — it is NOT branch_list/pr_list/recent_history (those are 0–290ms or disabled). It is entirely inside status(), and specifically get_records fetching every full live document to hash it for drift detection.

Timings (0.4.4, remote store, warm client)

/api/state handler calls:

call time
make_engine (cached after 1st) 396ms first / 1ms after
whoami 0ms
status 3840ms
branch_list / pr_list disabled here (0ms)
recent_history(50) 287ms

Inside status():

sub-call time
_all_refs(include_history=True) 880ms
_batch_live_and_heads(refs) (310 refs) 1952ms
get_records(collB, 224 ids) 2065ms
get_heads(collB, 224 ids) 563ms
get_records(collA, 75 ids) 276ms
get_heads(collA, 75 ids) 666ms
list_record_ids(collA) 586ms

Root cause

status() computes hash_doc(live) per record to compare against the stored head oid — so it must fetch the full live doc of every tracked record. One collection has 224 records with large docs (nested config/schema/pricing), so get_records alone transfers a few MB = ~2s. This is inherent to "pull live, hash, compare against head." It's not a forgotten projection (that was #28); it's the drift check itself.

Suggestions

  1. Parallelize the per-collection get_records/get_heads. perf(ui): /api/state still ~5s on remote store — serialize-to-parallel the remaining per-collection round-trips (follow-up to #28) #31 added _gather, but within _batch_live_and_heads the per-collection full-doc fetches still run such that the ~2s big-collection transfer isn't overlapped with the others. Fanning the collections out concurrently → wall-clock ≈ max(collection) ≈ ~2s instead of ~4s.
  2. Avoid transferring full docs for the drift check (the real win). Persist the content hash on the head record at commit time, and detect drift with a cheap server-side comparison instead of pulling+hashing every live doc client-side — e.g. a stored content_hash field on the live doc updated by cfgit writes (compare hashes, only fetch the full doc when they differ / when the user opens a diff). That takes status from "fetch every doc" (~4s) to "compare N hashes" (~200ms). Bigger change; the payoff is status staying flat as configs grow.
  3. Lazy status for the UI: /api/state could return the ref list + head metadata immediately and compute live-vs-head drift per-row on demand (when a row is expanded), so first paint isn't blocked on hashing all N docs.

Net: gets remote-store status from ~4s to sub-second and keeps it flat as the number/size of tracked docs grows.

(Profiled on 0.4.4. Timing script available.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions