@@ -17,6 +17,7 @@ import { Bench, hrtimeNow } from "tinybench";
1717
1818/** @typedef {import("tinybench").Task } TinybenchTask */
1919/** @typedef {import("tinybench").Fn } Fn */
20+ /** @typedef {import("tinybench").FnOptions } FnOptions */
2021/** @typedef {import("../types.d.ts") } Webpack */
2122/** @typedef {import("../types.d.ts").Configuration } Configuration */
2223/** @typedef {import("../types.d.ts").Stats } Stats */
@@ -154,6 +155,10 @@ async function getBaselineRevs() {
154155 * @returns {number } distribution
155156 */
156157function tDistribution ( n ) {
158+ if ( n === 0 ) {
159+ return 1 ;
160+ }
161+
157162 // two-sided, 90%
158163 // https://en.wikipedia.org/wiki/Student%27s_t-distribution
159164 if ( n <= 30 ) {
@@ -473,7 +478,8 @@ function getCallingFile() {
473478 return path . relative ( gitDir , callingFile ) ;
474479}
475480
476- /** @typedef {Map<string, string> } URIMap */
481+ /** @typedef {{ uri: string, fn: Fn, options: FnOptions | undefined } } TaskMeta */
482+ /** @typedef {Map<string, TaskMeta> } URIMap */
477483
478484/** @type {WeakMap<Bench, URIMap> } */
479485const taskUriMap = new WeakMap ( ) ;
@@ -500,7 +506,7 @@ function getOrCreateUriMap(bench) {
500506 */
501507function getTaskUri ( bench , taskName , rootCallingFile ) {
502508 const uriMap = taskUriMap . get ( bench ) ;
503- return uriMap ?. get ( taskName ) || `${ rootCallingFile } ::${ taskName } ` ;
509+ return uriMap ?. get ( taskName ) ?. uri || `${ rootCallingFile } ::${ taskName } ` ;
504510}
505511
506512/**
@@ -516,23 +522,23 @@ const withCodSpeed = async (bench) => {
516522
517523 const rawAdd = bench . add ;
518524 const uriMap = getOrCreateUriMap ( bench ) ;
519- bench . add = ( name , fn , opts ) => {
525+ bench . add = ( name , fn , options ) => {
520526 const callingFile = getCallingFile ( ) ;
521527 let uri = callingFile ;
522528 if ( bench . name !== undefined ) {
523529 uri += `::${ bench . name } ` ;
524530 }
525531 uri += `::${ name } ` ;
526- uriMap . set ( name , uri ) ;
527- return rawAdd . bind ( bench ) ( name , fn , opts ) ;
532+ uriMap . set ( name , { uri, fn , options } ) ;
533+ return rawAdd . bind ( bench ) ( name , fn , options ) ;
528534 } ;
529535 const rootCallingFile = getCallingFile ( ) ;
530536
531537 if ( codspeedRunnerMode === "instrumented" ) {
532538 const setupBenchRun = ( ) => {
533539 setupCore ( ) ;
534540 console . log (
535- "[CodSpeed] running with @codspeed/tinybench (instrumented mode)"
541+ "[CodSpeed] running with @codspeed/tinybench (simulation mode)"
536542 ) ;
537543 } ;
538544 const finalizeBenchRun = ( ) => {
@@ -571,21 +577,23 @@ const withCodSpeed = async (bench) => {
571577
572578 /**
573579 * @param {Task } task task
580+ * @param {string } name task name
574581 * @returns {Promise<[number, number] | void> } start and end time
575582 */
576- const iterationAsync = async ( task ) => {
577- // @ts -expect-error no public API
578- const { fn, fnOpts } = task ;
583+ const iterationAsync = async ( task , name ) => {
584+ const { fn, options } =
585+ /** @type {TaskMeta } */
586+ ( uriMap . get ( name ) ) ;
579587
580588 try {
581- await fnOpts . beforeEach ?. call ( task , "run" ) ;
582- const start = bench . opts . now ( ) ;
589+ await options ? .beforeEach ?. call ( task , "run" ) ;
590+ const start = bench . now ( ) ;
583591 await fn ( ) ;
584- const end = bench . opts . now ( ) - start || 0 ;
585- await fnOpts . afterEach ?. call ( this , "run" ) ;
592+ const end = bench . now ( ) - start || 0 ;
593+ await options ? .afterEach ?. call ( task , "run" ) ;
586594 return [ start , end ] ;
587595 } catch ( err ) {
588- if ( bench . opts . throws ) {
596+ if ( bench . throws ) {
589597 throw err ;
590598 }
591599 }
@@ -606,57 +614,61 @@ const withCodSpeed = async (bench) => {
606614
607615 /**
608616 * @param {Task } task task
617+ * @param {string } name task name
609618 * @param {string } uri URI
610619 */
611- const runTaskAsync = async ( task , uri ) => {
612- // @ts -expect-error no public API
613- const { fnOpts, fn } = task ;
620+ const runTaskAsync = async ( task , name , uri ) => {
621+ const { fn, options } =
622+ /** @type {TaskMeta } */
623+ ( uriMap . get ( name ) ) ;
614624
615625 // Custom setup
616- await bench . opts . setup ?. ( task , "run" ) ;
626+ await bench . setup ?. ( task , "run" ) ;
617627
618- await fnOpts ?. beforeAll ?. call ( task , "run" ) ;
628+ await options ?. beforeAll ?. call ( task , "run" ) ;
619629
620630 // Custom warmup
621631 // We don't run `optimizeFunction` because our function is never optimized, instead we just warmup webpack
622632 const samples = [ ] ;
623633
624- while ( samples . length < bench . opts . iterations - 1 ) {
625- samples . push ( await iterationAsync ( task ) ) ;
634+ while ( samples . length < bench . iterations - 1 ) {
635+ samples . push ( await iterationAsync ( task , name ) ) ;
626636 }
627637
628- await fnOpts ?. beforeEach ?. call ( task , "run" ) ;
638+ await options ?. beforeEach ?. call ( task , "run" ) ;
629639 await mongoMeasurement . start ( uri ) ;
630640 global . gc ?. ( ) ;
631641 await wrapWithInstrumentHooksAsync ( wrapFunctionWithFrame ( fn , true ) , uri ) ;
632642 await mongoMeasurement . stop ( uri ) ;
633- await fnOpts ?. afterEach ?. call ( task , "run" ) ;
643+ await options ?. afterEach ?. call ( task , "run" ) ;
634644 console . log ( `[Codspeed] ✔ Measured ${ uri } ` ) ;
635- await fnOpts ?. afterAll ?. call ( task , "run" ) ;
645+ await options ?. afterAll ?. call ( task , "run" ) ;
636646
637647 // Custom teardown
638- await bench . opts . teardown ?. ( task , "run" ) ;
648+ await bench . teardown ?. ( task , "run" ) ;
639649
640650 logTaskCompletion ( uri , taskCompletionMessage ( ) ) ;
641651 } ;
642652
643653 /**
644654 * @param {Task } task task
655+ * @param {string } name task
645656 * @returns {[number, number] | undefined } start and end time
646657 */
647- const iteration = ( task ) => {
648- // @ts -expect-error no public API
649- const { fn, fnOpts } = task ;
658+ const iteration = ( task , name ) => {
659+ const { fn, options } =
660+ /** @type {TaskMeta } */
661+ ( uriMap . get ( name ) ) ;
650662
651663 try {
652- fnOpts . beforeEach ?. call ( task , "run" ) ;
653- const start = bench . opts . now ( ) ;
664+ options ? .beforeEach ?. call ( task , "run" ) ;
665+ const start = bench . now ( ) ;
654666 fn ( ) ;
655- const end = bench . opts . now ( ) - start || 0 ;
656- fnOpts . afterEach ?. call ( this , "run" ) ;
667+ const end = bench . now ( ) - start || 0 ;
668+ options ? .afterEach ?. call ( task , "run" ) ;
657669 return [ start , end ] ;
658670 } catch ( err ) {
659- if ( bench . opts . throws ) {
671+ if ( bench . throws ) {
660672 throw err ;
661673 }
662674 }
@@ -677,34 +689,36 @@ const withCodSpeed = async (bench) => {
677689
678690 /**
679691 * @param {Task } task task
692+ * @param {string } name task name
680693 * @param {string } uri URI
681694 */
682- const runTaskSync = ( task , uri ) => {
683- // @ts -expect-error no public API
684- const { fnOpts, fn } = task ;
695+ const runTaskSync = ( task , name , uri ) => {
696+ const { fn, options } =
697+ /** @type {TaskMeta } */
698+ ( uriMap . get ( name ) ) ;
685699
686700 // Custom setup
687- bench . opts . setup ?. ( task , "run" ) ;
701+ bench . setup ?. ( task , "run" ) ;
688702
689- fnOpts ?. beforeAll ?. call ( task , "run" ) ;
703+ options ?. beforeAll ?. call ( task , "run" ) ;
690704
691705 // Custom warmup
692706 const samples = [ ] ;
693707
694- while ( samples . length < bench . opts . iterations - 1 ) {
695- samples . push ( iteration ( task ) ) ;
708+ while ( samples . length < bench . iterations - 1 ) {
709+ samples . push ( iteration ( task , name ) ) ;
696710 }
697711
698- fnOpts ?. beforeEach ?. call ( task , "run" ) ;
712+ options ?. beforeEach ?. call ( task , "run" ) ;
699713
700714 wrapWithInstrumentHooks ( wrapFunctionWithFrame ( fn , false ) , uri ) ;
701715
702- fnOpts ?. afterEach ?. call ( task , "run" ) ;
716+ options ?. afterEach ?. call ( task , "run" ) ;
703717 console . log ( `[Codspeed] ✔ Measured ${ uri } ` ) ;
704- fnOpts ?. afterAll ?. call ( task , "run" ) ;
718+ options ?. afterAll ?. call ( task , "run" ) ;
705719
706720 // Custom teardown
707- bench . opts . teardown ?. ( task , "run" ) ;
721+ bench . teardown ?. ( task , "run" ) ;
708722
709723 logTaskCompletion ( uri , taskCompletionMessage ( ) ) ;
710724 } ;
@@ -722,9 +736,8 @@ const withCodSpeed = async (bench) => {
722736 setupBenchRun ( ) ;
723737
724738 for ( const task of bench . tasks ) {
725- // @ts -expect-error no public API
726- const uri = getTaskUri ( task . bench , task . name , rootCallingFile ) ;
727- await runTaskAsync ( task , uri ) ;
739+ const uri = getTaskUri ( bench , task . name , rootCallingFile ) ;
740+ await runTaskAsync ( task , task . name , uri ) ;
728741 }
729742
730743 return finalizeAsyncRun ( ) ;
@@ -734,9 +747,8 @@ const withCodSpeed = async (bench) => {
734747 setupBenchRun ( ) ;
735748
736749 for ( const task of bench . tasks ) {
737- // @ts -expect-error no public API
738- const uri = getTaskUri ( task . bench , task . name , rootCallingFile ) ;
739- runTaskSync ( task , uri ) ;
750+ const uri = getTaskUri ( bench , task . name , rootCallingFile ) ;
751+ runTaskSync ( task , task . name , uri ) ;
740752 }
741753
742754 return finalizeSyncRun ( ) ;
@@ -1195,14 +1207,18 @@ bench.addEventListener("cycle", (event) => {
11951207 throw new Error ( "Can't find a task" ) ;
11961208 }
11971209
1198- const runs = task . runs ;
1199- const nSqrt = Math . sqrt ( runs ) ;
1200- const z = tDistribution ( runs - 1 ) ;
1201-
12021210 if ( ! task . result ) {
12031211 throw new Error ( "Can't find a task result" ) ;
12041212 }
12051213
1214+ if ( task . result . state !== "completed" ) {
1215+ throw new Error ( `Task is not completed, state is ${ task . result . state } ` ) ;
1216+ }
1217+
1218+ const runs = task . runs ;
1219+ const nSqrt = Math . sqrt ( runs ) ;
1220+ const z = tDistribution ( runs - 1 ) ;
1221+
12061222 const { latency } = task . result ;
12071223 const minConfidence = latency . mean - ( z * latency . sd ) / nSqrt ;
12081224 const maxConfidence = latency . mean + ( z * latency . sd ) / nSqrt ;
0 commit comments