@typed/fx 0.0.32 → 0.0.34

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.
Files changed (55) hide show
  1. package/.eslintcache +1 -1
  2. package/cjs/Subject.js +2 -2
  3. package/cjs/Subject.js.map +1 -1
  4. package/cjs/_internal.d.ts +1 -1
  5. package/cjs/_internal.d.ts.map +1 -1
  6. package/esm/Subject.js +2 -2
  7. package/esm/Subject.js.map +1 -1
  8. package/esm/_internal.d.ts +1 -1
  9. package/esm/_internal.d.ts.map +1 -1
  10. package/package.json +27 -31
  11. package/perf/cases/filter-map-reduce.ts +30 -38
  12. package/perf/helpers.ts +54 -0
  13. package/src/Subject.test.ts +1 -1
  14. package/src/Subject.ts +2 -2
  15. package/src/combine.test.ts +1 -1
  16. package/src/continueWith.test.ts +1 -1
  17. package/src/debounce.test.ts +1 -1
  18. package/src/delay.test.ts +1 -1
  19. package/src/during.test.ts +1 -1
  20. package/src/exhaustMap.test.ts +1 -1
  21. package/src/exhaustMapLatest.test.ts +1 -1
  22. package/src/exhaustMapList.test.ts +1 -1
  23. package/src/filterLoop.test.ts +1 -1
  24. package/src/filterMap.test.ts +1 -1
  25. package/src/flatMap.test.ts +1 -1
  26. package/src/flatMapConcurrently.test.ts +1 -1
  27. package/src/hold.test.ts +1 -1
  28. package/src/mapCause.test.ts +1 -1
  29. package/src/mapEffect.test.ts +1 -1
  30. package/src/merge.test.ts +1 -1
  31. package/src/multicast.test.ts +1 -1
  32. package/src/orElse.test.ts +1 -1
  33. package/src/periodic.test.ts +1 -1
  34. package/src/provide.test.ts +1 -1
  35. package/src/since.test.ts +1 -1
  36. package/src/skipRepeats.test.ts +1 -1
  37. package/src/skipWhile.test.ts +1 -1
  38. package/src/slice.test.ts +1 -1
  39. package/src/snapshot.test.ts +1 -1
  40. package/src/switchMap.test.ts +1 -1
  41. package/src/takeWhile.test.ts +1 -1
  42. package/src/throttle.test.ts +1 -1
  43. package/src/until.test.ts +1 -1
  44. package/src/withEmitter.test.ts +1 -1
  45. package/src/zip.test.ts +1 -1
  46. package/src/zipIterable.test.ts +1 -1
  47. package/tools/benchmark.ts +179 -0
  48. package/perf/_internal.ts +0 -153
  49. package/perf/cases/flatMap.ts +0 -49
  50. package/perf/cases/switchMap.ts +0 -36
  51. package/perf/readme-base.md +0 -14
  52. package/perf/readme.md +0 -40
  53. package/perf/runFullSuite.ts +0 -37
  54. package/perf/runPerfTest.ts +0 -18
  55. package/perf/tsconfig.json +0 -7
@@ -0,0 +1,54 @@
1
+ import * as Effect from '@effect/core/io/Effect'
2
+ import * as MC from '@most/core'
3
+ import * as MS from '@most/scheduler'
4
+ import { asap } from '@most/scheduler'
5
+ import * as MT from '@most/types'
6
+ import * as rxjs from 'rxjs'
7
+
8
+ import * as Fx from '../src/index'
9
+ import { PerformanceTestCase } from '../tools/benchmark.js'
10
+
11
+ export function effectTest<E, A>(init: () => Effect.Effect<never, E, A>) {
12
+ return PerformanceTestCase('@effect/io/Effect', init, Effect.unsafeRunPromise)
13
+ }
14
+
15
+ export function rxjsTest<A>(init: () => rxjs.Observable<A>) {
16
+ return PerformanceTestCase('rxjs @7', init, (o) => new Promise((resolve) => o.subscribe(resolve)))
17
+ }
18
+
19
+ export function mostTest<A>(init: (fromArray: typeof mostFromArray) => MT.Stream<A>) {
20
+ const scheduler = MS.newDefaultScheduler()
21
+
22
+ return PerformanceTestCase(
23
+ '@most/core',
24
+ () => init(mostFromArray),
25
+ (o) => MC.runEffects(o, scheduler),
26
+ )
27
+ }
28
+
29
+ export function mostFromArray<A>(array: readonly A[]): MT.Stream<A> {
30
+ const l = array.length
31
+ return MC.newStream((sink, scheduler) =>
32
+ asap(
33
+ {
34
+ run(t) {
35
+ for (let i = 0; i < l; ++i) {
36
+ sink.event(t, array[i])
37
+ }
38
+ sink.end(t)
39
+ },
40
+ error(t, e) {
41
+ sink.error(t, e)
42
+ },
43
+ dispose() {
44
+ // Nothing to dispose
45
+ },
46
+ },
47
+ scheduler,
48
+ ),
49
+ )
50
+ }
51
+
52
+ export function fxTest<E, A>(init: () => Fx.Fx<never, E, A>) {
53
+ return PerformanceTestCase('@typed/fx', () => Fx.runDrain(init()), Effect.unsafeRunPromise)
54
+ }
@@ -2,7 +2,7 @@ import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
4
  import * as Fiber from '@effect/core/io/Fiber'
5
- import { pipe } from '@fp-ts/data/Function'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
package/src/Subject.ts CHANGED
@@ -113,10 +113,10 @@ export namespace RefSubject {
113
113
  updateSome: (f) => ref.updateSome(f),
114
114
  updateSomeAndGet: (f) => ref.updateSomeAndGet(f),
115
115
  run: h.run.bind(h),
116
- emit: h.emit.bind(h),
116
+ emit: ref.set,
117
117
  failCause: h.failCause.bind(h),
118
118
  end: h.end,
119
- unsafeEmit: (a) => Effect.unsafeRunAsync(h.emit(a)),
119
+ unsafeEmit: (a) => Effect.unsafeRunAsync(ref.set(a)),
120
120
  unsafeFailCause: (c) => Effect.unsafeRunAsync(h.failCause(c)),
121
121
  unsafeEnd: () => Effect.unsafeRunAsync(h.end),
122
122
  }
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
 
6
6
  import * as Fx from './index.js'
7
7
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import { millis } from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
package/src/delay.test.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual, ok } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -4,8 +4,8 @@ import * as Effect from '@effect/core/io/Effect'
4
4
  import * as Fiber from '@effect/core/io/Fiber'
5
5
  import * as TestClock from '@effect/core/testing/TestClock'
6
6
  import { TestEnvironment } from '@effect/core/testing/TestEnvironment'
7
- import { pipe } from '@fp-ts/data/Function'
8
7
  import { millis } from '@tsplus/stdlib/data/Duration'
8
+ import { pipe } from '@tsplus/stdlib/data/Function'
9
9
 
10
10
  import * as Fx from './index.js'
11
11
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -4,8 +4,8 @@ import * as Effect from '@effect/core/io/Effect'
4
4
  import * as Fiber from '@effect/core/io/Fiber'
5
5
  import * as TestClock from '@effect/core/testing/TestClock'
6
6
  import { TestEnvironment } from '@effect/core/testing/TestEnvironment'
7
- import { pipe } from '@fp-ts/data/Function'
8
7
  import { millis } from '@tsplus/stdlib/data/Duration'
8
+ import { pipe } from '@tsplus/stdlib/data/Function'
9
9
 
10
10
  import * as Fx from './index.js'
11
11
 
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
  import * as Maybe from '@tsplus/stdlib/data/Maybe'
6
6
 
7
7
  import * as Fx from './index.js'
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
  import * as Maybe from '@tsplus/stdlib/data/Maybe'
6
6
 
7
7
  import * as Fx from './index.js'
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
package/src/hold.test.ts CHANGED
@@ -2,8 +2,8 @@ import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
4
  import * as Fiber from '@effect/core/io/Fiber'
5
- import { pipe } from '@fp-ts/data/Function'
6
5
  import * as Duration from '@tsplus/stdlib/data/Duration'
6
+ import { pipe } from '@tsplus/stdlib/data/Function'
7
7
 
8
8
  import * as Fx from './index.js'
9
9
 
@@ -3,7 +3,7 @@ import { deepEqual } from 'assert'
3
3
  import * as Cause from '@effect/core/io/Cause'
4
4
  import * as Effect from '@effect/core/io/Effect'
5
5
  import * as Exit from '@effect/core/io/Exit'
6
- import { pipe } from '@fp-ts/data/Function'
6
+ import { pipe } from '@tsplus/stdlib/data/Function'
7
7
 
8
8
  import * as Fx from './index.js'
9
9
 
@@ -1,7 +1,7 @@
1
1
  import { deepEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
 
6
6
  import * as Fx from './index.js'
7
7
 
package/src/merge.test.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
 
6
6
  import * as Fx from './index.js'
7
7
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
 
6
6
  import * as Fx from './index.js'
7
7
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import { millis } from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import { periodic } from './periodic.js'
8
8
  import { runCollect } from './runCollect.js'
@@ -2,7 +2,7 @@ import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
4
  import * as Scope from '@effect/core/io/Scope'
5
- import { pipe } from '@fp-ts/data/Function'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
  import { Tag } from '@tsplus/stdlib/service/Tag'
7
7
 
8
8
  import * as Fx from './index.js'
package/src/since.test.ts CHANGED
@@ -4,8 +4,8 @@ import * as Effect from '@effect/core/io/Effect'
4
4
  import * as Fiber from '@effect/core/io/Fiber'
5
5
  import * as TestClock from '@effect/core/testing/TestClock'
6
6
  import { TestEnvironment } from '@effect/core/testing/TestEnvironment'
7
- import { pipe } from '@fp-ts/data/Function'
8
7
  import { millis } from '@tsplus/stdlib/data/Duration'
8
+ import { pipe } from '@tsplus/stdlib/data/Function'
9
9
 
10
10
  import * as Fx from './index.js'
11
11
 
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
  import * as Equivalence from '@tsplus/stdlib/prelude/Equivalence'
6
6
 
7
7
  import * as Fx from './index.js'
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
 
6
6
  import * as Fx from './index.js'
7
7
 
package/src/slice.test.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
 
6
6
  import * as Fx from './index.js'
7
7
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
 
6
6
  import * as Fx from './index.js'
7
7
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import { millis } from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
package/src/until.test.ts CHANGED
@@ -4,8 +4,8 @@ import * as Effect from '@effect/core/io/Effect'
4
4
  import * as Fiber from '@effect/core/io/Fiber'
5
5
  import * as TestClock from '@effect/core/testing/TestClock'
6
6
  import { TestEnvironment } from '@effect/core/testing/TestEnvironment'
7
- import { pipe } from '@fp-ts/data/Function'
8
7
  import { millis } from '@tsplus/stdlib/data/Duration'
8
+ import { pipe } from '@tsplus/stdlib/data/Function'
9
9
 
10
10
  import * as Fx from './index.js'
11
11
 
@@ -1,7 +1,7 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
4
+ import { pipe } from '@tsplus/stdlib/data/Function'
5
5
 
6
6
  import * as Fx from './index.js'
7
7
 
package/src/zip.test.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -1,8 +1,8 @@
1
1
  import { deepStrictEqual } from 'assert'
2
2
 
3
3
  import * as Effect from '@effect/core/io/Effect'
4
- import { pipe } from '@fp-ts/data/Function'
5
4
  import * as Duration from '@tsplus/stdlib/data/Duration'
5
+ import { pipe } from '@tsplus/stdlib/data/Function'
6
6
 
7
7
  import * as Fx from './index.js'
8
8
 
@@ -0,0 +1,179 @@
1
+ import tablemark from 'tablemark'
2
+
3
+ export interface PerformanceTestCase<A> {
4
+ readonly name: string
5
+ readonly init: () => A
6
+ readonly run: (a: A) => unknown | Promise<unknown>
7
+ }
8
+
9
+ export function PerformanceTestCase<A>(
10
+ name: string,
11
+ init: () => A,
12
+ run: (a: A) => Promise<unknown>,
13
+ ): PerformanceTestCase<A> {
14
+ return { name, init, run }
15
+ }
16
+
17
+ export interface InitResult {
18
+ readonly startTime: number
19
+ readonly endTime: number
20
+ }
21
+
22
+ export interface TestResult {
23
+ readonly startTime: number
24
+ readonly endTime: number
25
+ }
26
+
27
+ export function TestResult(startTime: number, endTime: number): TestResult {
28
+ return { startTime, endTime }
29
+ }
30
+
31
+ export interface TestStats {
32
+ readonly average: number
33
+ readonly min: number
34
+ readonly max: number
35
+ readonly timeToInit: number
36
+ readonly percentile: number
37
+ }
38
+
39
+ export function TestStats(
40
+ average: number,
41
+ min: number,
42
+ max: number,
43
+ timeToInit: number,
44
+ percentile: number,
45
+ ): TestStats {
46
+ return { average, min, max, timeToInit, percentile }
47
+ }
48
+
49
+ export interface TestSuite {
50
+ readonly name: string
51
+ readonly tests: ReadonlyArray<PerformanceTestCase<any>>
52
+ }
53
+
54
+ export function TestSuite(name: string, tests: ReadonlyArray<PerformanceTestCase<any>>): TestSuite {
55
+ return { name, tests }
56
+ }
57
+
58
+ export interface TestSuiteResult {
59
+ readonly name: string
60
+ readonly stats: Readonly<Record<string, TestStats>>
61
+ }
62
+
63
+ export function TestSuiteResult(
64
+ name: string,
65
+ stats: Readonly<Record<string, TestStats>>,
66
+ ): TestSuiteResult {
67
+ return { name, stats }
68
+ }
69
+
70
+ export interface RunTestConfig {
71
+ readonly iterations: number
72
+ readonly getTime: () => number
73
+ }
74
+
75
+ export function RunTestConfig(iterations: number, getTime: () => number): RunTestConfig {
76
+ return { iterations, getTime }
77
+ }
78
+
79
+ export function runTestCaseWith(config: RunTestConfig) {
80
+ return async <A>(test: PerformanceTestCase<A>): Promise<Readonly<Record<string, TestStats>>> => {
81
+ const { iterations, getTime } = config
82
+ const initStartTime = getTime()
83
+ const init = test.init()
84
+ const initEndTime = getTime()
85
+ const results: TestResult[] = []
86
+
87
+ for (let i = 0; i < iterations; i++) {
88
+ const startTime = getTime()
89
+ await test.run(init)
90
+ const endTime = getTime()
91
+ results.push(TestResult(startTime, endTime))
92
+ }
93
+
94
+ return buildStats({
95
+ [test.name]: [
96
+ {
97
+ startTime: initStartTime,
98
+ endTime: initEndTime,
99
+ },
100
+ results,
101
+ ] as const,
102
+ })
103
+ }
104
+ }
105
+
106
+ export async function runTestSuite(
107
+ suite: TestSuite,
108
+ config: RunTestConfig,
109
+ ): Promise<TestSuiteResult> {
110
+ let results: Record<string, TestStats> = {}
111
+ const runTestCase = runTestCaseWith(config)
112
+
113
+ for (const test of suite.tests) {
114
+ results = { ...results, ...(await runTestCase(test)) }
115
+ }
116
+
117
+ return TestSuiteResult(suite.name, addPercentile(results))
118
+ }
119
+
120
+ function buildStats(
121
+ results: Record<string, readonly [InitResult, readonly TestResult[]]>,
122
+ ): Readonly<Record<string, TestStats>> {
123
+ const stats: Record<string, TestStats> = {}
124
+
125
+ for (const [name, [initResult, testResults]] of Object.entries(results)) {
126
+ const durations = testResults.map((r) => r.endTime - r.startTime)
127
+ const average = durations.reduce((a, b) => a + b, 0) / durations.length
128
+ const min = Math.min(...durations)
129
+ const max = Math.max(...durations)
130
+
131
+ stats[name] = TestStats(
132
+ roundNumber(average),
133
+ roundNumber(min),
134
+ roundNumber(max),
135
+ roundNumber(initResult.endTime - initResult.startTime),
136
+ -1, // Needs to be calculated later
137
+ )
138
+ }
139
+
140
+ return stats
141
+ }
142
+
143
+ function roundNumber(n: number): number {
144
+ return parseFloat(n.toFixed(4))
145
+ }
146
+
147
+ function addPercentile(
148
+ stats: Readonly<Record<string, TestStats>>,
149
+ ): Readonly<Record<string, TestStats>> {
150
+ const newStats: Record<string, TestStats> = {}
151
+
152
+ const fastestToSlowest = Object.entries(stats).sort(([, a], [, b]) => a.average - b.average)
153
+ const fastestTime = fastestToSlowest[0][1].average
154
+
155
+ for (let i = 0; i < fastestToSlowest.length; ++i) {
156
+ const [name, stat] = fastestToSlowest[i]
157
+ newStats[name] = TestStats(
158
+ stat.average,
159
+ stat.min,
160
+ stat.max,
161
+ stat.timeToInit,
162
+ roundNumber(stat.average / fastestTime),
163
+ )
164
+ }
165
+
166
+ return newStats
167
+ }
168
+
169
+ export function printTestSuiteResult(result: TestSuiteResult): string {
170
+ return `## ${result.name}
171
+
172
+ ${tablemark(
173
+ Object.entries(result.stats).map(([library, stats]) => ({
174
+ library,
175
+ ...stats,
176
+ })),
177
+ )}
178
+ `
179
+ }