@remnic/bench 9.3.726 → 9.3.728
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -9
- package/baselines/coding-graph-baseline.json +13 -11
- package/dist/index.d.ts +29 -3
- package/dist/index.js +1589 -84
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -211,7 +211,8 @@ A dedicated benchmark suite for [`@remnic/coding-graph`](https://www.npmjs.com/p
|
|
|
211
211
|
|---|---|
|
|
212
212
|
| `fullIndexMs` | Wall time to index the entire fixture in one batch. |
|
|
213
213
|
| `fullIndexLocsPerSecond` | Sustained LOC/s during full index (higher is better). |
|
|
214
|
-
| `incrementalUpdateP50Ms` / `incrementalUpdateP95Ms` | Single-file re-ingest latency (p50/p95 over ≥20 iterations). |
|
|
214
|
+
| `incrementalUpdateP50Ms` / `incrementalUpdateP95Ms` | Single-file re-ingest latency for UNCHANGED content (the common-case no-op path; p50/p95 over ≥20 iterations). |
|
|
215
|
+
| `incrementalModifiedUpdateP50Ms` / `incrementalModifiedUpdateP95Ms` | Single-file re-ingest latency for MODIFIED content — the change-heavy path (edge deletion/creation, symbol re-resolution). Complementary to `incrementalUpdate` (#1688). |
|
|
215
216
|
| `tracePathP95Ms` | `trace_path` (BFS, depth ≤ 5) p95. |
|
|
216
217
|
| `searchGraphP95Ms` | `search_graph` name-pattern p95. |
|
|
217
218
|
| `deadCodeMs` | Dead-code query wall time. |
|
|
@@ -225,18 +226,21 @@ The harness ships a **deterministic** synthetic repo generator (`generateSynthet
|
|
|
225
226
|
|
|
226
227
|
The measured numbers live in [`baselines/coding-graph-baseline.json`](./baselines/coding-graph-baseline.json) — bench-owned, separate from the structural ratchets in `scripts/ratchet-baseline.json`. The regression gate (`checkCodingGraphRegression`) compares a report against the baseline with a generous tolerance (default 30%). It hard-fails on gross regression — a real failing step, not a warning (rule 50). Tightening the baseline is a deliberate PR act (mirrors `check-ratchets --update`).
|
|
227
228
|
|
|
229
|
+
The gate carries a **machine-fingerprint guard** (`compareMachineFingerprints`): when the report's machine class differs from the baseline's (arch/platform/Node major/cpuModel/cores), the comparison is *skipped* (`passed: true`, `skipped: true`, `machineMismatch` populated) rather than failed, so a cross-machine CI run does not false-positive on legitimate hardware variance (#1688). Regenerate the baseline on the target machine class for a real comparison.
|
|
230
|
+
|
|
228
231
|
### Measured numbers (first baseline)
|
|
229
232
|
|
|
230
233
|
> Numbers below are from the **baseline JSON file** — this section is checked against it so prose can't drift from measurement. Run `remnic bench coding-graph` to reproduce.
|
|
231
234
|
|
|
232
235
|
| Metric | Value | Machine |
|
|
233
236
|
|---|---|---|
|
|
234
|
-
| Full index | ~
|
|
235
|
-
| Incremental update p95 | ~0.
|
|
236
|
-
|
|
|
237
|
-
|
|
|
238
|
-
|
|
|
239
|
-
|
|
|
237
|
+
| Full index | ~15 ms, ~131k LOC/s | Apple M2 Max, Node v22 |
|
|
238
|
+
| Incremental update p95 (idempotent) | ~0.24 ms | Apple M2 Max |
|
|
239
|
+
| Incremental modified update p95 (change-heavy) | ~0.96 ms | Apple M2 Max |
|
|
240
|
+
| trace_path p95 | ~0.13 ms | Apple M2 Max |
|
|
241
|
+
| search_graph p95 | ~0.18 ms | Apple M2 Max |
|
|
242
|
+
| dead_code | ~0.53 ms | Apple M2 Max |
|
|
243
|
+
| DB size | ~270 KB/KLOC | Apple M2 Max |
|
|
240
244
|
|
|
241
245
|
These are **working targets on a small fixture (20 files, 200 symbols)**, NOT parity claims against codebase-memory-mcp's published numbers (28M LOC in 3 min, <1ms Cypher). Scale targets at 1M+ LOC are tracked as stretch goals — the harness will measure them when Tier-L fixtures are wired (issue #1557 PR2).
|
|
242
246
|
|
|
@@ -245,9 +249,14 @@ These are **working targets on a small fixture (20 files, 200 symbols)**, NOT pa
|
|
|
245
249
|
```typescript
|
|
246
250
|
import { runCodingGraphBenchmark, checkCodingGraphRegression } from "@remnic/bench";
|
|
247
251
|
|
|
252
|
+
// Use the SAME fixture as the bundled baseline (20×10, density 0.3, seed
|
|
253
|
+
// 42) so the regression gate compares like-for-like. A custom fixture
|
|
254
|
+
// (different fileCount/symbolsPerFile/callDensity/seed/language) needs its
|
|
255
|
+
// OWN baseline — build one with buildBaselineFromReport(report, note) and
|
|
256
|
+
// commit it, otherwise checkCodingGraphRegression reports a fixture mismatch.
|
|
248
257
|
const report = await runCodingGraphBenchmark({
|
|
249
|
-
fixture: { fileCount:
|
|
250
|
-
iterations:
|
|
258
|
+
fixture: { seed: 42, fileCount: 20, symbolsPerFile: 10, callDensity: 0.3, language: "typescript" },
|
|
259
|
+
iterations: 20,
|
|
251
260
|
});
|
|
252
261
|
|
|
253
262
|
const baseline = require("@remnic/bench/baselines/coding-graph-baseline.json");
|
|
@@ -256,4 +265,7 @@ if (!gate.passed) {
|
|
|
256
265
|
console.error(gate.summary);
|
|
257
266
|
process.exit(1);
|
|
258
267
|
}
|
|
268
|
+
// gate.skipped === true when the report's machine fingerprint differs from
|
|
269
|
+
// the baseline's (different CPU/arch/Node major) — the comparison is skipped
|
|
270
|
+
// rather than failed so cross-machine CI does not false-positive (#1688).
|
|
259
271
|
```
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"schemaVersion":
|
|
2
|
+
"schemaVersion": 2,
|
|
3
3
|
"machine": {
|
|
4
4
|
"arch": "arm64",
|
|
5
5
|
"platform": "darwin",
|
|
@@ -16,15 +16,17 @@
|
|
|
16
16
|
"language": "typescript"
|
|
17
17
|
},
|
|
18
18
|
"metrics": {
|
|
19
|
-
"fullIndexMs":
|
|
20
|
-
"fullIndexLocsPerSecond":
|
|
21
|
-
"incrementalUpdateP50Ms": 0.
|
|
22
|
-
"incrementalUpdateP95Ms": 0.
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"
|
|
19
|
+
"fullIndexMs": 15.452540999999655,
|
|
20
|
+
"fullIndexLocsPerSecond": 131111,
|
|
21
|
+
"incrementalUpdateP50Ms": 0.173167000000376,
|
|
22
|
+
"incrementalUpdateP95Ms": 0.23908399999982066,
|
|
23
|
+
"incrementalModifiedUpdateP50Ms": 0.6047909999997501,
|
|
24
|
+
"incrementalModifiedUpdateP95Ms": 0.9565000000002328,
|
|
25
|
+
"tracePathP95Ms": 0.13425000000006548,
|
|
26
|
+
"searchGraphP95Ms": 0.1764170000001286,
|
|
27
|
+
"deadCodeMs": 0.5299169999998412,
|
|
28
|
+
"dbBytesPerKloc": 270468
|
|
27
29
|
},
|
|
28
|
-
"createdAt": "2026-07-
|
|
29
|
-
"note": "
|
|
30
|
+
"createdAt": "2026-07-07T12:35:48.738Z",
|
|
31
|
+
"note": "Regenerated baseline — adds incrementalModifiedUpdate metric (#1688 item 1) + machine-fingerprint guard (#1688 item 2). WAL-aware DB sizing retained (#1557 PR1)."
|
|
30
32
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3979,7 +3979,7 @@ interface WallMetric {
|
|
|
3979
3979
|
* The regression gate compares only keys present in BOTH the report and
|
|
3980
3980
|
* the baseline — new metrics are additive, never blocking.
|
|
3981
3981
|
*/
|
|
3982
|
-
type CodingGraphMetricKey = "fullIndexMs" | "fullIndexLocsPerSecond" | "incrementalUpdateP50Ms" | "incrementalUpdateP95Ms" | "tracePathP95Ms" | "searchGraphP95Ms" | "deadCodeMs" | "dbBytesPerKloc";
|
|
3982
|
+
type CodingGraphMetricKey = "fullIndexMs" | "fullIndexLocsPerSecond" | "incrementalUpdateP50Ms" | "incrementalUpdateP95Ms" | "incrementalModifiedUpdateP50Ms" | "incrementalModifiedUpdateP95Ms" | "tracePathP95Ms" | "searchGraphP95Ms" | "deadCodeMs" | "dbBytesPerKloc";
|
|
3983
3983
|
interface CodingGraphBenchReport {
|
|
3984
3984
|
/** Schema version — bump when the report shape changes. */
|
|
3985
3985
|
readonly schemaVersion: number;
|
|
@@ -3996,8 +3996,14 @@ interface CodingGraphBenchReport {
|
|
|
3996
3996
|
readonly fullIndexMs: WallMetric;
|
|
3997
3997
|
/** LOC/s sustained during full index (higher is better). */
|
|
3998
3998
|
readonly fullIndexLocsPerSecond: number;
|
|
3999
|
-
/** Incremental single-file update latency distribution
|
|
3999
|
+
/** Incremental single-file update latency distribution (idempotent
|
|
4000
|
+
* re-ingest of UNCHANGED content — the common-case no-op path). */
|
|
4000
4001
|
readonly incrementalUpdate: MicroMetric;
|
|
4002
|
+
/** Incremental MODIFIED-content re-ingest latency distribution. A
|
|
4003
|
+
* complementary metric to `incrementalUpdate`: measures the change-heavy
|
|
4004
|
+
* path (edge deletion/creation, symbol re-resolution) rather than the
|
|
4005
|
+
* cache-hit no-op (#1688 item 1). */
|
|
4006
|
+
readonly incrementalModifiedUpdate: MicroMetric;
|
|
4001
4007
|
/** trace_path (depth ≤ 5) latency distribution. */
|
|
4002
4008
|
readonly tracePath: MicroMetric;
|
|
4003
4009
|
/** search_graph name-pattern latency distribution. */
|
|
@@ -4046,6 +4052,24 @@ interface RegressionGateResult {
|
|
|
4046
4052
|
readonly passed: boolean;
|
|
4047
4053
|
readonly regressions: readonly RegressionMetricDetail[];
|
|
4048
4054
|
readonly summary: string;
|
|
4055
|
+
/**
|
|
4056
|
+
* True when the gate SKIPPED the metric comparison because of a
|
|
4057
|
+
* non-fatal precondition (machine-fingerprint mismatch). `passed` is
|
|
4058
|
+
* also true in that case — a hardware variance must not fail CI (#1688
|
|
4059
|
+
* item 2). Callers that want to treat a skip as informational can check
|
|
4060
|
+
* this flag.
|
|
4061
|
+
*/
|
|
4062
|
+
readonly skipped?: boolean;
|
|
4063
|
+
/**
|
|
4064
|
+
* Present when `skipped` is true due to a machine-fingerprint mismatch
|
|
4065
|
+
* between the report and the baseline. Lists the fingerprint fields that
|
|
4066
|
+
* differ so a human can decide whether the comparison is still meaningful.
|
|
4067
|
+
*/
|
|
4068
|
+
readonly machineMismatch?: {
|
|
4069
|
+
readonly report: MachineFingerprint;
|
|
4070
|
+
readonly baseline: MachineFingerprint;
|
|
4071
|
+
readonly differingFields: readonly string[];
|
|
4072
|
+
};
|
|
4049
4073
|
}
|
|
4050
4074
|
interface CodingGraphBenchConfig {
|
|
4051
4075
|
/** Fixture parameters. Defaults to a small, fast smoke fixture. */
|
|
@@ -4073,7 +4097,7 @@ declare const MIN_ITERATIONS = 20;
|
|
|
4073
4097
|
/** Default regression tolerance (issue #1557: generous, e.g. 30%). */
|
|
4074
4098
|
declare const DEFAULT_TOLERANCE_PERCENT = 30;
|
|
4075
4099
|
/** Report schema version — bump when the shape changes. */
|
|
4076
|
-
declare const CODING_GRAPH_BENCH_SCHEMA_VERSION =
|
|
4100
|
+
declare const CODING_GRAPH_BENCH_SCHEMA_VERSION = 2;
|
|
4077
4101
|
|
|
4078
4102
|
/**
|
|
4079
4103
|
* Deterministic synthetic repo generator (issue #1557 design (a)).
|
|
@@ -4169,6 +4193,8 @@ declare const METRIC_DIRECTION: {
|
|
|
4169
4193
|
fullIndexLocsPerSecond: "higher-is-better";
|
|
4170
4194
|
incrementalUpdateP95Ms: "lower-is-better";
|
|
4171
4195
|
incrementalUpdateP50Ms: "lower-is-better";
|
|
4196
|
+
incrementalModifiedUpdateP95Ms: "lower-is-better";
|
|
4197
|
+
incrementalModifiedUpdateP50Ms: "lower-is-better";
|
|
4172
4198
|
tracePathP95Ms: "lower-is-better";
|
|
4173
4199
|
searchGraphP95Ms: "lower-is-better";
|
|
4174
4200
|
deadCodeMs: "lower-is-better";
|