feat(bench): add benchmark harness to tests and tooling (closes #936) - #1021
Open
arcgod-design wants to merge 1 commit into
Open
feat(bench): add benchmark harness to tests and tooling (closes #936)#1021arcgod-design wants to merge 1 commit into
arcgod-design wants to merge 1 commit into
Conversation
…shanGK#936) Adds a zero-dependency microbenchmark framework at backend/utils/benchmark_harness.py for retrieval-pipeline performance: - BenchmarkSpec (name, callable, warmup_runs, runs, timeout, baseline) - run_benchmark(spec, tasks, clock=time.perf_counter) -> BenchResult Runs the callable once per task per 'runs' iteration. Warmup runs are discarded. Failures (exceptions) are caught and recorded; the loop continues onto the next task. Per-task latencies pooled into summary stats: min/max/mean/median/stdev/p95/p99. - compare_to_baseline(result, baseline) returns mean/median/p95 ratios + {regressed: bool} flag (true if any ratio exceeds REGRESSION_FACTOR=1.5). Use as a CI gate on PRs that slow retrieval by >50%. - write_report(results, path) persists JSON to disk. - All time normalised to milliseconds regardless of clock unit. The existing chromadb_benchmark.py is left in place — it tests the real chromadb+sentence-transformers stack and runs ONLY in the heavy-dep environment. This harness ships with no such deps and works in any Python 3.10+ environment, making it suitable for unit tests, local dev, and PR-time micro-regression checks on synthetic retrievers. New tooling: scripts/benchmark_harness_cli.py — reads a JSON config describing one or more benchmarks (each with a dotted 'module:func' callable), runs each, prints JSON output, optionally writes a JSON report (--out) and emits a baseline drift comparison (--compare). Exit codes: 0/1/2/3 following the repo's CLI conventions. New tests: backend/tests/test_benchmark_harness.py — 23 cases: - TestPercentile (6): empty, single, p0=min, p100=max, interpolate-p50, interpolate-p95. - TestRunBenchmarkHappyPath (2): latencies recorded, summary stats populated. - TestWarmupRuns (1): warmup invocations NOT recorded. - TestFailureHandling (2): exception marks failed, remaining tasks continue. - TestCustomClock (1): deterministic injected clock yields exactly expected ms latencies. - TestEmptyTasks (1): zero-task path yields zeroed summary. - TestCompareToBaseline (4): None baseline, equal baseline no signal, regression flagged at >1.5x, zero-baseline protected against /0. - TestWriteReport (3): writes JSON, creates parent dirs, round-trips. - TestDataclassShape (3): defaults, TaskResult.to_dict, BenchResult .to_dict keys. Acceptance criteria from issue imDarshanGK#936: [x] Implement the change in the tests and tooling [x] Add or update tests, docs, or validation for the touched path
|
@arcgod-design is attempting to deploy a commit to the Darshan's projects Team on Vercel. A member of the Team first needs to authorize it. |
Owner
|
@arcgod-design |
adikulkarni006
approved these changes
Jul 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds a zero-dependency microbenchmark harness for retrieval pipeline performance, with tests and CLI tooling — closing issue #936.
The existing
backend/tests/test_chromadb_benchmark.pymeasures real chromadb + sentence-transformer latency but can only run when those heavy deps are installed (sentence-transformers alone times out on the local Windows env, requires GPU for reasonable latency). This PR adds a deferred, dependency-free harness that:compare_to_baseline()helper for CI regression gating.Why
Retrieval pipeline regressions are hard to catch in PRs because:
benchmark_harnessaddresses all three:run_benchmark(spec, tasks, clock)— runsspec.callable_(task)once per task perrunsiteration. Warmup runs are discarded. Per-invocationtime.perf_counter()deltas are normalised to ms. Exceptions incallable_are caught (task markedfailed); the loop continues onto the next task so one bug doesn't kill the whole run.compare_to_baseline(result, baseline)— emitsmean_ratio / median_ratio / p95_ratioand aregressed: boolflag set if any of the three exceedsREGRESSION_FACTOR=1.5. Drop this into a CI gate and you get automatic PR-block on 50%+ regressions without bolting onto the existing workflow's stdout scraping.write_report(results, path)— JSON-serialises the wholeBenchResult(per-task latencies + pooled summary) so future PRs can diff against the committed baseline.What changed
Backend utility —
backend/utils/benchmark_harness.py(NEW)Public surface:
Internals:
_percentile(sorted_values, p)— linear-interpolation percentile, indistinguishable fromstatistics.quantilesfor monotonic inputs, but defined forp ∈ [0,100]inclusive.REGRESSION_FACTOR = 1.5— the soft cap above which a benchmark is flagged as regressed.Tooling —
scripts/benchmark_harness_cli.py(NEW)Reads a JSON file describing one or more benchmarks, each with a dotted
module:callableimport path, runs them, prints a JSON report, optionally writes a report file (--out) and emits baseline-drift comparison (--compare). Exit codes0/1/2/3per repo convention.Example:
Tests —
backend/tests/test_benchmark_harness.py(NEW, 23 cases)TestPercentilep0=min,p100=max, interpolate-p50, interpolate-p95TestRunBenchmarkHappyPathTestWarmupRunslatencies_msTestFailureHandlingTestCustomClockTestEmptyTasksTestCompareToBaselineTestWriteReportTestDataclassShapeBenchmarkSpecdefaults,TaskResult.to_dict,BenchResult.to_dictkeysVerification
The existing
test_chromadb_benchmark.pyis unchanged and continues to require chromadb + sentence-transformers (intentionally — it's the only way to benchmark the real stack under load). This new harness complements it: zero-dependent unit-tests in every env + PR-time regression gate.Acceptance criteria
Closes #936.