@@ -26,7 +26,7 @@ import minimist from 'minimist';
2626import path from 'path' ;
2727import { ConstraintSystemSummary } from '../provable/core/provable-context.js' ;
2828
29- export { PerfRegressionEntry , Performance } ;
29+ export { PerfRegressionEntry , Performance , logPerf } ;
3030
3131type MethodsInfo = Record <
3232 string ,
@@ -357,27 +357,35 @@ function checkAgainstBaseline(params: {
357357 }
358358
359359 // tolerances
360- const compileTol = 1.05 ; // 5 %
361- const compileTiny = 1.08 ; // for near-zero baselines
360+ const compileTol = 1.08 ; // 8 %
361+ const compileTiny = 1.1 ; // 10% for near-zero baselines (< 5e-5s)
362362 const timeTolDefault = 1.1 ; // 10% for prove/verify
363363 const timeTolSmall = 1.25 ; // 25% for very small times (<0.2s)
364364
365+ const labelPretty = label [ 0 ] . toUpperCase ( ) + label . slice ( 1 ) ;
366+
365367 if ( label === 'compile' ) {
366368 const expected = baseline . compileTime ;
367369 if ( expected == null ) {
368370 throw new Error (
369371 `No baseline compileTime for "${ programName } ". Run --dump (compile) to set it.`
370372 ) ;
371373 }
374+
372375 const tol = expected < 5e-5 ? compileTiny : compileTol ;
373376 const allowedPct = ( tol - 1 ) * 100 ;
377+ const regressionPct = expected === 0 ? 0 : ( ( actualTime - expected ) / expected ) * 100 ;
378+ const failed = actualTime > expected * tol ;
374379
375- if ( actualTime > expected * tol ) {
376- const regressionPct = ( ( actualTime - expected ) / expected ) * 100 ;
380+ // colorized perf log
381+ logPerf ( programName , label , expected , actualTime , regressionPct , allowedPct , failed ) ;
382+
383+ if ( failed ) {
377384 throw new Error (
378385 `Compile regression for ${ programName } \n` +
379- ` Actual: ${ actualTime . toFixed ( 6 ) } s\n` +
380- ` Regression: +${ regressionPct . toFixed ( 2 ) } % (allowed +${ allowedPct . toFixed ( 0 ) } %)`
386+ ` Actual: ${ actualTime . toFixed ( 6 ) } s\n` +
387+ ` Baseline: ${ expected . toFixed ( 6 ) } s\n` +
388+ ` Regression: +${ Number . isFinite ( regressionPct ) ? regressionPct . toFixed ( 2 ) : '∞' } % (allowed +${ allowedPct . toFixed ( 0 ) } %)`
381389 ) ;
382390 }
383391 return ;
@@ -390,6 +398,7 @@ function checkAgainstBaseline(params: {
390398 `No baseline method entry for ${ programName } .${ methodName } . Run --dump (${ label } ) to add it.`
391399 ) ;
392400 }
401+
393402 if ( baseMethod . digest !== digest ) {
394403 throw new Error (
395404 `Digest mismatch for ${ programName } .${ methodName } \n` +
@@ -399,21 +408,65 @@ function checkAgainstBaseline(params: {
399408 }
400409
401410 const expected = label === 'prove' ? baseMethod . proveTime : baseMethod . verifyTime ;
402- const labelPretty = label . charAt ( 0 ) . toUpperCase ( ) ;
403411 if ( expected == null ) {
404412 throw new Error (
405413 `No baseline ${ label } Time for ${ programName } .${ methodName } . Run --dump (${ label } ) to set it.`
406414 ) ;
407415 }
416+
408417 const tol = expected < 0.2 ? timeTolSmall : timeTolDefault ;
409418 const allowedPct = ( tol - 1 ) * 100 ;
419+ const regressionPct = expected === 0 ? 0 : ( ( actualTime - expected ) / expected ) * 100 ;
420+ const failed = actualTime > expected * tol ;
421+
422+ logPerf (
423+ `${ programName } .${ methodName } ` ,
424+ label ,
425+ expected ,
426+ actualTime ,
427+ regressionPct ,
428+ allowedPct ,
429+ failed
430+ ) ;
410431
411- if ( actualTime > expected * tol ) {
412- const regressionPct = ( ( actualTime - expected ) / expected ) * 100 ;
432+ if ( failed ) {
413433 throw new Error (
414434 `${ labelPretty } regression for ${ programName } .${ methodName } \n` +
415- ` Actual: ${ actualTime . toFixed ( 3 ) } s\n` +
416- ` Regression: +${ regressionPct . toFixed ( 2 ) } % (allowed +${ allowedPct . toFixed ( 0 ) } %)`
435+ ` Actual: ${ actualTime . toFixed ( 3 ) } s\n` +
436+ ` Baseline: ${ expected . toFixed ( 3 ) } s\n` +
437+ ` Regression: +${ Number . isFinite ( regressionPct ) ? regressionPct . toFixed ( 2 ) : '∞' } % (allowed +${ allowedPct . toFixed ( 0 ) } %)`
417438 ) ;
418439 }
419440}
441+
442+ function logPerf (
443+ scope : string ,
444+ label : string ,
445+ expected : number ,
446+ actual : number ,
447+ regressionPct : number ,
448+ allowedPct : number ,
449+ failed : boolean
450+ ) {
451+ const COLORS = {
452+ reset : '\x1b[0m' ,
453+ red : '\x1b[31m' ,
454+ green : '\x1b[32m' ,
455+ yellow : '\x1b[33m' ,
456+ cyan : '\x1b[36m' ,
457+ } ;
458+
459+ let color : string ;
460+ if ( failed ) color = COLORS . red ;
461+ else if ( regressionPct > 0 ) color = COLORS . yellow ;
462+ else color = COLORS . green ;
463+
464+ console . log (
465+ `${ COLORS . cyan } [Perf][${ scope } ]${ COLORS . reset } ${ label } : ` +
466+ `baseline=${ expected . toFixed ( 6 ) } s, actual=${ actual . toFixed ( 6 ) } s, ` +
467+ `${ color } regression=${ regressionPct >= 0 ? '+' : '' } ${
468+ Number . isFinite ( regressionPct ) ? regressionPct . toFixed ( 2 ) : '∞'
469+ } %${ COLORS . reset } ` +
470+ `(allowed +${ allowedPct . toFixed ( 0 ) } %)`
471+ ) ;
472+ }
0 commit comments