Skip to content

Commit 5821ac3

Browse files
committed
Modularize performance regression framework
1 parent 1b4ab4b commit 5821ac3

File tree

1 file changed

+93
-55
lines changed

1 file changed

+93
-55
lines changed

src/lib/testing/perf-regression.ts

Lines changed: 93 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -156,83 +156,53 @@ function createPerformanceSession(
156156
const perfRegressionJson: Record<string, PerfRegressionEntry> = JSON.parse(raw);
157157

158158
if (label === 'compile') {
159-
// CHECK: validate against baseline (no writes)
160-
if (CHECK) {
161-
checkAgainstBaseline({
162-
perfRegressionJson,
163-
programName,
164-
label: 'compile', // compile checks don't use method/digest; pass empty strings
165-
methodName: '',
166-
digest: '',
167-
actualTime: time,
168-
});
169-
return;
170-
}
171-
172159
// DUMP: update only contract-level compileTime
173160
if (DUMP) {
174-
const prev = perfRegressionJson[programName];
175-
const merged: PerfRegressionEntry = prev
176-
? { ...prev, compileTime: time }
177-
: { compileTime: time, methods: {} };
161+
dumpCompile(perfRegressionJson, programName, time);
162+
return;
163+
}
178164

179-
perfRegressionJson[programName] = merged;
180-
fs.writeFileSync(FILE_PATH, JSON.stringify(perfRegressionJson, null, 2));
165+
// CHECK: validate against baseline (no writes)
166+
if (CHECK) {
167+
checkCompile(perfRegressionJson, programName, time);
181168
return;
182169
}
183170
}
184171

185172
if (label === 'prove') {
186-
// For prove we need the analyzed methods and a valid methodName
187-
if (!cs) return;
188-
189-
const csMethodNames = Object.keys(cs);
190-
if (csMethodNames.length === 0) return;
173+
// Require analyzed methods summary when proving
174+
if (!cs) {
175+
throw new Error(
176+
'methodsSummary is required for "prove". Pass it to Performance.create(programName, methodsSummary).'
177+
);
178+
}
191179

180+
// Require the specific method name
192181
if (!methodName) {
193182
throw new Error(
194-
'Please provide the method name you are proving (pass it to start(..., methodName)).'
183+
'Please provide the method name you are proving (start("prove", methodName)).'
195184
);
196185
}
197186

198-
if (!Object.prototype.hasOwnProperty.call(cs, methodName)) {
187+
// Look up the method; error if missing (also covers empty methodsSummary)
188+
const info = cs[methodName as keyof typeof cs];
189+
if (!info) {
190+
const available = Object.keys(cs);
199191
throw new Error(
200192
`The method "${methodName}" does not exist in the analyzed constraint system for "${programName}". ` +
201-
`Available: ${csMethodNames.join(', ')}`
193+
`Available: ${available.length ? available.join(', ') : '(none)'}`
202194
);
203195
}
204196

205-
const info = cs[methodName];
206-
if (!info) return;
207-
208-
// CHECK: validate only, no writes
209-
if (CHECK) {
210-
checkAgainstBaseline({
211-
perfRegressionJson,
212-
programName,
213-
label: 'prove',
214-
methodName,
215-
digest: info.digest,
216-
actualTime: time,
217-
});
197+
// DUMP: update per-method rows/digest and proveTime; leave compileTime untouched
198+
if (DUMP) {
199+
dumpProve(perfRegressionJson, programName, methodName, info, time);
218200
return;
219201
}
220202

221-
// DUMP: update per-method rows/digest and proveTime; leave compileTime untouched
222-
if (DUMP) {
223-
const prev = perfRegressionJson[programName];
224-
const merged: PerfRegressionEntry = prev
225-
? { ...prev, methods: { ...prev.methods } }
226-
: { methods: {} };
227-
228-
merged.methods[methodName] = {
229-
rows: info.rows,
230-
digest: info.digest,
231-
proveTime: time,
232-
};
233-
234-
perfRegressionJson[programName] = merged;
235-
fs.writeFileSync(FILE_PATH, JSON.stringify(perfRegressionJson, null, 2));
203+
// CHECK: validate only, no writes
204+
if (CHECK) {
205+
checkProve(perfRegressionJson, programName, methodName, info.digest, time);
236206
return;
237207
}
238208
}
@@ -270,6 +240,74 @@ const Performance = {
270240

271241
// HELPERS
272242

243+
function dumpCompile(
244+
perfRegressionJson: Record<string, PerfRegressionEntry>,
245+
programName: string,
246+
time: number
247+
) {
248+
const prev = perfRegressionJson[programName];
249+
const merged: PerfRegressionEntry = prev
250+
? { ...prev, compileTime: time }
251+
: { compileTime: time, methods: {} };
252+
253+
perfRegressionJson[programName] = merged;
254+
fs.writeFileSync(FILE_PATH, JSON.stringify(perfRegressionJson, null, 2));
255+
}
256+
257+
function dumpProve(
258+
perfRegressionJson: Record<string, PerfRegressionEntry>,
259+
programName: string,
260+
methodName: string,
261+
info: ConstraintSystemSummary,
262+
time: number
263+
) {
264+
const prev = perfRegressionJson[programName];
265+
const merged: PerfRegressionEntry = prev
266+
? { ...prev, methods: { ...prev.methods } }
267+
: { methods: {} };
268+
269+
merged.methods[methodName] = {
270+
rows: info.rows,
271+
digest: info.digest,
272+
proveTime: time,
273+
};
274+
275+
perfRegressionJson[programName] = merged;
276+
fs.writeFileSync(FILE_PATH, JSON.stringify(perfRegressionJson, null, 2));
277+
}
278+
279+
function checkCompile(
280+
perfRegressionJson: Record<string, PerfRegressionEntry>,
281+
programName: string,
282+
actualTime: number
283+
) {
284+
checkAgainstBaseline({
285+
perfRegressionJson,
286+
programName,
287+
label: 'compile', // compile checks don't use method/digest; pass empty strings
288+
methodName: '',
289+
digest: '',
290+
actualTime,
291+
});
292+
}
293+
294+
function checkProve(
295+
perfRegressionJson: Record<string, PerfRegressionEntry>,
296+
programName: string,
297+
methodName: string,
298+
digest: string,
299+
actualTime: number
300+
) {
301+
checkAgainstBaseline({
302+
perfRegressionJson,
303+
programName,
304+
label: 'prove',
305+
methodName,
306+
digest,
307+
actualTime,
308+
});
309+
}
310+
273311
/**
274312
* Compare a measured time/digest against stored baselines.
275313
* Throws an error if regression exceeds tolerance.

0 commit comments

Comments
 (0)