Skip to content

perf: improve benchmark reliability with metric separation and fairness tracking#47

Merged
Nebu1eto merged 5 commits into
mainfrom
perf/phase0-measurement
Feb 11, 2026
Merged

perf: improve benchmark reliability with metric separation and fairness tracking#47
Nebu1eto merged 5 commits into
mainfrom
perf/phase0-measurement

Conversation

@Nebu1eto

Copy link
Copy Markdown
Owner

Summary

  • Split random-access benchmark into open+lookup (existing) and lookup-only (new) scenarios to isolate open vs lookup performance
  • Add cell-count fairness metric to rust-comparison benchmarks, verifying libraries do equivalent work
  • Enhance Node.js memory measurement with heapUsed alongside RSS and methodology documentation

Changes

A: Random-access Metric Separation

  • Rust: Extract random_cell_addresses() helper, add lookup-only scenario with Arc<Workbook> pre-open
  • Node: Add lookup-only variants for all 4 libraries (SheetKit sync/async, ExcelJS, SheetJS)

B: Fairness Metrics

  • Add cells_read: Option<u64> to BenchResult
  • Cell-counting probes for SheetKit, calamine, edit-xlsx
  • Console output includes cells=N, markdown report gets "Cells Read" column

C: Memory Measurement Enhancement

  • Track heapUsed alongside RSS in every benchmark run
  • Add methodology documentation explaining RSS vs heapUsed and measurement limitations
  • Detailed Statistics and Memory Usage tables show both metrics

Test plan

  • cargo build --workspace clean
  • cargo clippy --workspace no warnings
  • cargo fmt --check passes
  • Benchmark code compiles (runtime execution requires fixture files)

🤖 Generated with Claude Code

Nebu1eto and others added 4 commits February 11, 2026 22:45
Separating the file-open cost from the pure cell-lookup cost lets us
independently measure I/O overhead vs in-memory access performance.
The original open+lookup scenario is preserved for backward compatibility.

Rust: opens the file once via Arc<Workbook> before the measurement loop.
Node: pre-opens workbooks for all libraries (SheetKit sync/async, ExcelJS,
SheetJS) so each run benchmarks only the getCellValue / getCell loop.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When comparing libraries, timing alone can be misleading if one library
skips cells or reads a different number of values. Adding an explicit
cell count per library per scenario makes it easy to verify all
libraries are doing equivalent work, improving benchmark trustworthiness.

Each read scenario now probes actual cell counts before benchmarking.
The count is displayed in console output and included in the markdown
report's detailed statistics table.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
RSS delta alone can be misleading for napi-rs libraries because native
Rust memory is invisible to V8's heap metrics, while RSS captures OS-level
overhead that may not reflect actual library usage. Adding heapUsed as a
complementary metric lets readers distinguish JS-heap growth from native
memory growth.

Both metrics measure post-operation residual (not peak), which is now
explicitly documented in the methodology section, console output headers,
and the BenchResult interface comments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@claude

claude Bot commented Feb 11, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@Nebu1eto

Copy link
Copy Markdown
Owner Author

리뷰 코멘트 공유드립니다.

  1. [P1] cells_read 공정성 지표 계산 방식이 라이브러리별로 달라 비교값이 왜곡될 수 있습니다.
  • SheetKit: sparse non-empty 셀 개수 합산 (cells.len())
  • calamine: row 폭(row.len()) 합산 (빈 셀 포함 가능)
  • 참고: benchmarks/rust-comparison/src/main.rs:297, benchmarks/rust-comparison/src/main.rs:313
  • 영향: PR 목표인 "동등 작업량 검증" 지표의 의미가 흔들릴 수 있습니다.
  1. [P2] lookup-only 시나리오에서 warmup/measured run이 동일 workbook 인스턴스를 재사용해, 내부 캐시 효과가 측정에 과도 반영될 수 있습니다.
  • 참고: benchmarks/node/benchmark.ts:139, benchmarks/node/benchmark.ts:1054
  • 영향: 재현성/공정성이 떨어질 수 있으며, steady-state cache benchmark로 성격이 바뀔 수 있습니다.

참고로 로컬에서 PR 브랜치 기준 아래는 통과 확인했습니다.

  • cargo check --manifest-path benchmarks/rust/Cargo.toml
  • cargo check --manifest-path benchmarks/rust-comparison/Cargo.toml

Address PR #47 review feedback:

[P1] cells_read fairness: calamine counted row.len() (including empty
cells) and edit-xlsx counted all read_cell() successes (including
format-only cells). Both now filter to non-empty cells only, matching
SheetKit's sparse iterator behavior for comparable work verification.

[P2] lookup-only cache reuse: the scenario shared a single workbook
instance across warmup and measured runs, causing internal caches to
accumulate. Rust benchmarks now open a fresh Workbook per run inside
make_fn (outside timing). Node.js benchmarks open a fresh instance
inside each callback (open cost included but applied equally).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@Nebu1eto
Nebu1eto merged commit 85fe947 into main Feb 11, 2026
7 checks passed
@Nebu1eto
Nebu1eto deleted the perf/phase0-measurement branch February 11, 2026 15:17
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.

1 participant