@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.
- package/.eslintcache +1 -1
- package/cjs/Subject.js +2 -2
- package/cjs/Subject.js.map +1 -1
- package/cjs/_internal.d.ts +1 -1
- package/cjs/_internal.d.ts.map +1 -1
- package/esm/Subject.js +2 -2
- package/esm/Subject.js.map +1 -1
- package/esm/_internal.d.ts +1 -1
- package/esm/_internal.d.ts.map +1 -1
- package/package.json +27 -31
- package/perf/cases/filter-map-reduce.ts +30 -38
- package/perf/helpers.ts +54 -0
- package/src/Subject.test.ts +1 -1
- package/src/Subject.ts +2 -2
- package/src/combine.test.ts +1 -1
- package/src/continueWith.test.ts +1 -1
- package/src/debounce.test.ts +1 -1
- package/src/delay.test.ts +1 -1
- package/src/during.test.ts +1 -1
- package/src/exhaustMap.test.ts +1 -1
- package/src/exhaustMapLatest.test.ts +1 -1
- package/src/exhaustMapList.test.ts +1 -1
- package/src/filterLoop.test.ts +1 -1
- package/src/filterMap.test.ts +1 -1
- package/src/flatMap.test.ts +1 -1
- package/src/flatMapConcurrently.test.ts +1 -1
- package/src/hold.test.ts +1 -1
- package/src/mapCause.test.ts +1 -1
- package/src/mapEffect.test.ts +1 -1
- package/src/merge.test.ts +1 -1
- package/src/multicast.test.ts +1 -1
- package/src/orElse.test.ts +1 -1
- package/src/periodic.test.ts +1 -1
- package/src/provide.test.ts +1 -1
- package/src/since.test.ts +1 -1
- package/src/skipRepeats.test.ts +1 -1
- package/src/skipWhile.test.ts +1 -1
- package/src/slice.test.ts +1 -1
- package/src/snapshot.test.ts +1 -1
- package/src/switchMap.test.ts +1 -1
- package/src/takeWhile.test.ts +1 -1
- package/src/throttle.test.ts +1 -1
- package/src/until.test.ts +1 -1
- package/src/withEmitter.test.ts +1 -1
- package/src/zip.test.ts +1 -1
- package/src/zipIterable.test.ts +1 -1
- package/tools/benchmark.ts +179 -0
- package/perf/_internal.ts +0 -153
- package/perf/cases/flatMap.ts +0 -49
- package/perf/cases/switchMap.ts +0 -36
- package/perf/readme-base.md +0 -14
- package/perf/readme.md +0 -40
- package/perf/runFullSuite.ts +0 -37
- package/perf/runPerfTest.ts +0 -18
- package/perf/tsconfig.json +0 -7
package/perf/helpers.ts
ADDED
|
@@ -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
|
+
}
|
package/src/Subject.test.ts
CHANGED
|
@@ -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 '@
|
|
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:
|
|
116
|
+
emit: ref.set,
|
|
117
117
|
failCause: h.failCause.bind(h),
|
|
118
118
|
end: h.end,
|
|
119
|
-
unsafeEmit: (a) => Effect.unsafeRunAsync(
|
|
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
|
}
|
package/src/combine.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
|
|
package/src/continueWith.test.ts
CHANGED
package/src/debounce.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 { 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
|
|
package/src/during.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
|
|
package/src/exhaustMap.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
|
|
|
@@ -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
|
|
package/src/filterLoop.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 '@
|
|
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'
|
package/src/filterMap.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 '@
|
|
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'
|
package/src/flatMap.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
|
|
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
|
|
package/src/mapCause.test.ts
CHANGED
|
@@ -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 '@
|
|
6
|
+
import { pipe } from '@tsplus/stdlib/data/Function'
|
|
7
7
|
|
|
8
8
|
import * as Fx from './index.js'
|
|
9
9
|
|
package/src/mapEffect.test.ts
CHANGED
package/src/merge.test.ts
CHANGED
package/src/multicast.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
|
|
package/src/orElse.test.ts
CHANGED
package/src/periodic.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 { 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'
|
package/src/provide.test.ts
CHANGED
|
@@ -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 '@
|
|
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
|
|
package/src/skipRepeats.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 '@
|
|
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'
|
package/src/skipWhile.test.ts
CHANGED
package/src/slice.test.ts
CHANGED
package/src/snapshot.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
|
|
package/src/switchMap.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
|
|
package/src/takeWhile.test.ts
CHANGED
package/src/throttle.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 { 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
|
|
package/src/withEmitter.test.ts
CHANGED
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
|
|
package/src/zipIterable.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
|
|
|
@@ -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
|
+
}
|