Skip to content

v0.4.67

Choose a tag to compare

@brunolau brunolau released this 05 Sep 13:06
· 104 commits to main since this release
6191848

v0.4.67

Performance: reference mock rows inherit their getters from a shared prototype (cache ON)

v0.4.66 made ReferenceQueryBuilder.createMockTargetRow() share one PropertyDescriptorMap
per (schema, alias, navigation path) signature — but every row still paid one
Object.defineProperties(row, descriptors), i.e. O(columns + relations) property
definitions per mock row, per query build. On a real workload that stayed the single largest
CPU item of query building: a V8 profile of the gopass-eshop order/create burst showed
createMockTargetRow self time at ~6 ms per order request (~40 % of the request's remaining
event-loop CPU) with the descriptor cache already on.

The descriptors' getters already read all per-row state through this-bound symbol slots, so
the shared object can be the row's prototype instead: MockRowCache now caches one
prototype object per signature (the descriptors applied once), and a mock row is
Object.create(prototype) plus its two own state slots — O(1) per row.

Behaviour

  • Switch OFF (default): unchanged memory profile — a fresh prototype is built and discarded per
    row, exactly as the fresh descriptor set was before.
  • Switch ON: identical query results; measured on the gopass-eshop checkout burst (30–100
    concurrent order/create, one process): 42–45 → 92–104 orders/s (v0.4.66 descriptor
    cache alone: 51–64), sequential p50 99 → 76 ms, GC self time −77 %.
  • MockRowCache.getOrBuild now builds/returns object prototypes (was PropertyDescriptorMap).
    setEnabled / isEnabled / diagnostics / reset are unchanged.

Internal consumers

Three selection resolvers used to recognise a navigation mock by probing its OWN properties
(Object.getOwnPropertyNames / Object.getOwnPropertyDescriptor / a plain-object prototype
check). Inherited getters are invisible to those, so they now go through
findFirstGetterKey (first enumerable getter, own or inherited) and isReferenceMockRow
(own state-slot marker). Root mocks (_createMockRow) keep their own getters and pass the same
probes unchanged.