Skip to content

perf(proxy): the #6595 store-plan gate costs one shape-table probe per allocated object #8125

Description

@proggeramlug

Summary

proxy.rs's #6595 store-plan gate calls object::object_is_regular exactly
once per allocated object
. It is the single largest piece of #8113's residual
instruction cost, and reducing it is a #6595-adjacent design question rather
than a mechanical fix — which is why #8113 left it alone.

The counts

Per-callsite counters (#[track_caller] + libc::atexit, on
tls_hot.rs::maybe_install_stats_hook's pattern) over every shape-table entry
point, on the 19-program corpus:

prog calls at object/mod.rs's object_is_regular probe per object
retain 3,000,000 1.00
retain1 1,000,000 1.00
retain_wide (8 fields) 3,000,000 1.00
retain_wide1 (8 fields) 1,000,000 1.00
churn 20,000,002
churn_read 1,000 ~0
tree, push_cls 0

One per object, flat in object width — 8-field literals cost the same as
2-field ones. Reads pay nothing.

Two further counter findings worth keeping:

  • object_live_slot_count is called ZERO times on every hot row. perf(object): remove the derivable object_type and field_count header words — 56 B -> 48 B #8113's
    new bound derivation is not on the measured path at all. Anyone reaching for a
    memo in front of it should check the call count first — two separate memo
    attempts measured null for exactly this reason.
  • deeplist records one call at this site yet carries the largest
    percentage (+8.2%). Whatever dominates deeplist is not this. Unexplained;
    the GC-pacing hypothesis (its RSS fell 4.2%) is plausible and unestablished.

Why it is not a mechanical fix

Before #8113 the gate was (*obj).object_type == OBJECT_TYPE_REGULAR — a free
u32 compare on a header word that no longer exists. The replacement must stay
FALSE for a heap class object or #6595 reopens (bundled zod's ZodX.create
vanishing from ClassRef static dispatch). Three candidates, none a drop-in:

  1. Pass the already-read GcHeader. The site has one in hand for its
    blocking-flags test; object_is_regular re-derives it through
    try_read_gc_header (handle-band, heap-range and slab classification, then
    the load). Tried in perf(object): remove the derivable object_type and field_count header words (56 B -> 48 B) [HELD: #8157 refuted; footprint-coupled residual + new #8094 guard cost] #8122 and REVERTED: semantically identical and
    strictly less work, yet a reproducible interp +9.59% / pipeline +4.43%
    (3-run best-of, quiet host) while doing nothing for retain (+3.26% ->
    +3.04%, noise). Mechanism unexplained — likely codegen/inlining, since the
    predicate provably does not change. Anyone retrying this must measure
    interp and pipeline, not just the retain family.
  2. PLAIN_ORDINARY_OBJ_FLAG (GcHeader._reserved bit 9), already in the
    register at this site and already re-tested by the emitted write PIC. But it
    is a narrow birth marker — set implies ordinary, clear does not imply class
    — so alone it silently drops store-plan eligibility for most ordinary
    objects.
  3. A process-global "any heap class object exists" short-circuit set by
    js_object_mark_class. Sound for the class question, but object_is_regular
    also returns false for FORWARDED and descriptor-less receivers, so skipping
    it changes those answers.

Acceptance

Refs #8113, #8122, #6595, #8098.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions