Skip to content

rqe cost export: count top-k heaps, time top-k queries above the clock floor, add exact hash-table overhead - #151

Merged
zzylol merged 2 commits into
mainfrom
rqe-cost-perop-fixes
Oct 6, 2026
Merged

zzylol merged 2 commits into
mainfrom
rqe-cost-perop-fixes

Conversation

@zzylol

@zzylol zzylol commented Oct 6, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #146. Part of #147 (the "Per-op fixes").

Why

The per-phase cost model (#145) multiplies each cost-table row's memory and CPU by deployment counts, so a per-instance error is multiplied too. Three rows were measured inconsistently:

  • CMS+heap and CountSketch+heap memory left out the top-k heap, while UnivMon counted its heaps. All three compete as TopK candidates, so they weren't compared like for like.
  • A top-k query is one heap dump per pass. That is about 0.1 µs, far below what getrusage can resolve, so the recorded query CPU was mostly the cost of the measurement itself.
  • Exact accumulators' memory counted keys and cells but not the hash table that holds them.

What

Only the benchmark's measurements change; the cost-table format is unchanged. After the next scripts/export_rqe_optimizer_costs.sh run:

  • the top-k rows' memory includes the heap;
  • the top-k rows' query CPU is the real cost of one heap dump;
  • the exact rows' memory includes hash-table overhead.

How

  • Heap memory: memory_cms_heap_lib_vector2d_{fast,regular} and memory_cs_heap_lib_vector2d_fast add CMS_HEAP_TOP_K × size_of::<HHItem>() (32 × 48 B), as memory_univmon_lib already does.
  • Query timing: TopkGT::probes() asks its one question 1024 times (QUERY_TIMING_REPEATS), as CardinalityGT does for HLL. The CMS-heap (fast and regular), CountSketch-heap and UnivMon top-k queries dump the heap once per probe. The work count is the number of answers, so CPU per op stays per call. Scoring uses the first answer, so accuracy is unchanged.
  • Exact memory: Multiple::footprint estimates hashbrown's table as capacity × (size_of key + size_of cell + 1 control byte), plus the strings and cell heap each group owns. Capacity is what is allocated, so the per-group share depends on the load factor at the measured group count: about 1.44 slots per group at the export's ~9.9k groups, and between 1 and 2 elsewhere.

Before this PR

Row Memory Query CPU per call
cms-heap 3×2048 24,576 B (counters only) 95.8 µs
countsketch-heap 3×2048 24,576 B (counters only) 2.8 µs
univmon-topk 3×1024, heap 500 heaps included 181 µs
exact-sum, per group 112 B (no table) —
exact-increase, per group 176 B (no table) —

Two top-k rows of the same shape differed 34× in query cost, and the numbers didn't track how much work a dump does.

After this PR

Row Memory Query CPU per call
cms-heap 3×2048 26,112 B (+1,536 B heap, +6%) 0.116 µs
countsketch-heap 3×2048 26,112 B (+1,536 B heap, +6%) 0.129 µs
univmon-topk 3×1024, heap 500 unchanged 6.44 µs (sorts its 500-item heap per dump)
exact-sum, per group 128 B (+14%) —
exact-increase, per group 220 B (+25%) —

Evidence

  • Query CPU: clnode109 (idle 56-core, load ≈ 1), release builds of f130b23 (before) and a8ee5ed (this PR), --operations query --metrics throughput,cpu --runs 5 --warmup-runs 3, zipf s=1.1, 1M items, 100k keys, seed 42. CPU per call = total query CPU ÷ total calls.

    Row Before: calls/pass, CPU/call After: calls/pass, CPU/call
    cms-heap 3×2048 1, 95.8 µs 1024, 0.116 µs
    countsketch-heap 3×2048 1, 2.8 µs 1024, 0.129 µs
    univmon-topk 3×1024, heap 500 1, 181 µs 1024, 6.44 µs
    univmon-topk 5×2048, heap 1000 1, 549 µs not measured (run stopped)
  • Memory: deterministic, from release builds of the same two commits (--operations insert --metrics throughput,memory). cms-heap 3×2048 24,576 → 26,112 B; countsketch-heap 5×2048 40,960 → 42,496 B; exact-sum on hydra_columns.yaml (9,950 groups) 1,117,624 → 1,272,312 B; exact-increase on counter_columns.yaml 1,754,424 → 2,189,816 B.

Verification

  • Unit tests: footprint_is_counters_plus_heap (cms_heap/mod.rs): the footprint is the counters plus a full heap of HHItems, for both the fast and regular paths. It replaces the old counters-only assertion.
  • End-to-end tests: the before/after runs above.
  • Other checks: cargo test --workspace, cargo clippy --workspace --all-targets -- -D warnings, CI (format-and-lint, test).

Architectural decisions

  • The heap counts at full capacity (32 entries), matching UnivMon rather than the current fill.
  • 1024 repeats, not HLL's 4096: a heap dump costs more than an HLL estimate, and 1024 already lifts a pass well above the clock floor.
  • UnivMon top-k repeats too: it shares TopkGT, and the three top-k families should be measured alike.
  • Exact memory is capacity-based (allocated bytes), not the length × ideal load factor; documented as measured at ~9.9k groups.

Limitations and follow-up

Human review — do not complete with an agent

  • The MVP boundary is correct.
  • New conceptual layers or public interfaces are necessary.
  • The before/after description matches the intended product behavior.
  • Human reviewer:
  • Decision and rationale:

🤖 Generated with Claude Code

…ash-table overhead

- CMS+heap and CountSketch+heap memory now adds CMS_HEAP_TOP_K HHItems,
  as UnivMon counts its heaps, so the TopK rows compare like for like (#146).
- TopkGT asks its one question 1024 times per pass, as CardinalityGT does,
  and the CMS/CS/UnivMon top-k queries answer once per probe, so a pass sits
  above the timer floor and work = answers keeps per-op CPU per call.
- Exact accumulators' footprint adds an estimate of hashbrown's table:
  capacity x (key + cell + 1 control byte).

Closes #146. Part of #147.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ctor dependence

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@zzylol

zzylol commented Oct 6, 2026

Copy link
Copy Markdown
Collaborator Author

Grilling outcome (agreed with @zzylol):

🤖 Generated with Claude Code

@zzylol
zzylol merged commit a8ee5ed into main Oct 6, 2026
2 checks passed
@zzylol zzylol changed the title rqe cost export: per-op fixes (top-k heap memory, top-k query timing, exact hash-table overhead) rqe cost export: count top-k heaps, time top-k queries above the clock floor, add exact hash-table overhead Oct 6, 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.

Top-k cost rows: CMS/CountSketch+heap exclude the heap from memory, UnivMon includes it

1 participant