Skip to content

Prefetch research: storage support matrix + measurement harness (loads vs. round-trips baseline) #4351

Description

@jensens

Part of the research plan for #4350 (see anchor comment there for the full decomposition).

Two prerequisites before touching any core code path: know which storages actually honor the hint, and be able to measure loads vs. round-trips so call-site choices are driven by numbers, not guesses.

All findings below are from a code scan of a Plone 6.2 coredev tree (2026-07-06); line numbers refer to the noted released versions.

Verified ground facts

  • ZODB.Connection.prefetch(*args) (ZODB 6.3, ZODB/Connection.py:1081) accepts oids (bytes), persistent objects (uses _p_oid), or iterables thereof. If the storage lacks prefetch, the method replaces itself with a no-op — calling it is unconditionally safe, no feature flag needed.
  • The MVCC adapter forwards with the connection's tid (ZODB/mvccadapter.py:192) — prefetch is connection-bound.

Part A — storage support matrix

Verify by code inspection plus one smoke test per storage:

  • RelStorage (documents cache prefetch) — ✅ implemented, bulk-fetch of uncached oids; smoke-tested on sqlite backend
  • ZEO ClientStorage — ✅ implemented, per-oid loadBefore but pipelined concurrently; smoke test: 50 cold misses → 0
  • FileStorage — ✅ confirmed no-op (self-replacing lambda in mvccadapter; MappingStorage/DemoStorage likewise)
  • zodb-pgjsonb — ✅ implemented since 1.15 (bluedynamics/zodb-pgjsonb#94), single ANY(...) query (code inspection; local smoke pending, coredev pins 1.13.0)
  • Confirm tid semantics per storage — consistent with the connection's MVCC view, see matrix comment

Deliverable: support table posted to #4350 done — see the matrix comment below.

Part B — measurement harness and baseline

  • Instrumentation counting object materializations (Connection.setstate calls) vs. actual storage round-trips (wrap storage.load* / use storage-side tracing; zodb-pgjsonb per-span tracing is prior art — bluedynamics/zodb-pgjsonb#96). The ratio objects/queries ≈ 1 identifies N+1; ≫ 1 identifies batched.
  • Fixture site: folder with N items, content with N relations, blocks with N resolveuid references.
  • Cold-cache vs. warm-cache runs against a networked storage (RelStorage and/or zodb-pgjsonb ≥ 1.15). FileStorage numbers are meaningless for round-trip analysis.
  • Baseline the hotspot inventory from the anchor comment: loads-per-render before/after per call site.

Deliverable: hotspot list ranked by measured wins — this ordering drives the sibling sub-issues.

Note for coredev: the current constraints pin zodb-pgjsonb 1.13.0; local benchmarking needs ≥ 1.15 (or RelStorage).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions