Skip to content

Commit 39491c8

Browse files
authored
chore: improve code size (#443)
* chore: reduce package size * reduce sligtly * reduce sligtly
1 parent fbcb3dc commit 39491c8

File tree

5 files changed

+96
-130
lines changed

5 files changed

+96
-130
lines changed

src/bench.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export class Bench extends EventTarget implements BenchLike {
4747
* - When `mode` is set to 'task', each task's iterations (calls of a task function) run concurrently.
4848
* - When `mode` is set to 'bench', different tasks within the bench run concurrently.
4949
*/
50-
readonly concurrency: 'bench' | 'task' | null = null
50+
readonly concurrency: 'bench' | 'task' | null
5151

5252
/**
5353
* The amount of executions per task.
@@ -107,7 +107,7 @@ export class Bench extends EventTarget implements BenchLike {
107107
* The maximum number of concurrent tasks to run
108108
* @default Number.POSITIVE_INFINITY
109109
*/
110-
readonly threshold = Number.POSITIVE_INFINITY
110+
readonly threshold: number
111111

112112
/**
113113
* Whether to throw an error if a task function throws
@@ -159,7 +159,7 @@ export class Bench extends EventTarget implements BenchLike {
159159
/**
160160
* The task map
161161
*/
162-
readonly #tasks = new Map<string, Task>()
162+
readonly #tasks: Map<string, Task> = new Map<string, Task>()
163163

164164
constructor (options: BenchOptions = {}) {
165165
super()
@@ -168,7 +168,7 @@ export class Bench extends EventTarget implements BenchLike {
168168
this.runtime = runtime
169169
this.runtimeVersion = runtimeVersion
170170
this.concurrency = restOptions.concurrency ?? null
171-
this.threshold = restOptions.threshold ?? Number.POSITIVE_INFINITY
171+
this.threshold = restOptions.threshold ?? Infinity
172172

173173
this.time = restOptions.time ?? defaultTime
174174
this.iterations = restOptions.iterations ?? defaultIterations

src/task.ts

Lines changed: 65 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import type {
1919
import { BenchEvent } from './event'
2020
import {
2121
assert,
22-
getStatisticsSorted,
22+
computeStatistics,
2323
isFnAsyncResource,
2424
isPromiseLike,
2525
isValidSamples,
@@ -339,41 +339,37 @@ export class Task extends EventTarget {
339339
): Promise<
340340
{ error: Error; samples?: never } | { error?: never; samples?: Samples }
341341
> {
342-
if (this.#fnOpts.beforeAll) {
343-
try {
342+
try {
343+
if (this.#fnOpts.beforeAll) {
344344
await this.#fnOpts.beforeAll.call(this, mode)
345-
} catch (error) {
346-
return { error: toError(error) }
347345
}
348-
}
349346

350-
let totalTime = 0 // ms
351-
const samples: number[] = []
347+
let totalTime = 0 // ms
348+
const samples: number[] = []
352349

353-
const benchmarkTask = async () => {
354-
if (this.#aborted) {
355-
return
356-
}
357-
try {
358-
if (this.#fnOpts.beforeEach != null) {
359-
await this.#fnOpts.beforeEach.call(this, mode)
350+
const benchmarkTask = async () => {
351+
if (this.#aborted) {
352+
return
360353
}
361-
362-
const taskTime = this.#async
363-
? await this.#measure()
364-
: this.#measureSync()
365-
366-
samples.push(taskTime)
367-
totalTime += taskTime
368-
} finally {
369-
if (this.#fnOpts.afterEach != null) {
370-
await this.#fnOpts.afterEach.call(this, mode)
354+
try {
355+
if (this.#fnOpts.beforeEach != null) {
356+
await this.#fnOpts.beforeEach.call(this, mode)
357+
}
358+
359+
const taskTime = this.#async
360+
? await this.#measure()
361+
: this.#measureSync()
362+
363+
samples.push(taskTime)
364+
totalTime += taskTime
365+
} finally {
366+
if (this.#fnOpts.afterEach != null) {
367+
await this.#fnOpts.afterEach.call(this, mode)
368+
}
371369
}
372370
}
373-
}
374371

375-
if (this.#bench.concurrency === 'task') {
376-
try {
372+
if (this.#bench.concurrency === 'task') {
377373
await withConcurrency({
378374
fn: benchmarkTask,
379375
iterations,
@@ -382,33 +378,25 @@ export class Task extends EventTarget {
382378
time,
383379
timestampProvider: this.#timestampProvider,
384380
})
385-
} catch (error) {
386-
return { error: toError(error) }
387-
}
388-
this.#runs = samples.length
389-
} else {
390-
try {
381+
this.#runs = samples.length
382+
} else {
391383
while (
392384
// eslint-disable-next-line no-unmodified-loop-condition
393385
(totalTime < time || samples.length < iterations) &&
394386
!this.#aborted
395387
) {
396388
await benchmarkTask()
397389
}
398-
} catch (error) {
399-
return { error: toError(error) }
400390
}
401-
}
402391

403-
if (this.#fnOpts.afterAll != null) {
404-
try {
392+
if (this.#fnOpts.afterAll != null) {
405393
await this.#fnOpts.afterAll.call(this, mode)
406-
} catch (error) {
407-
return { error: toError(error) }
408394
}
409-
}
410395

411-
return isValidSamples(samples) ? { samples } : {}
396+
return isValidSamples(samples) ? { samples } : {}
397+
} catch (error) {
398+
return { error: toError(error) }
399+
}
412400
}
413401

414402
/**
@@ -422,73 +410,65 @@ export class Task extends EventTarget {
422410
time: number,
423411
iterations: number
424412
): { error: Error; samples?: never } | { error?: never; samples?: Samples } {
425-
if (this.#fnOpts.beforeAll) {
426-
try {
413+
try {
414+
if (this.#fnOpts.beforeAll) {
427415
const beforeAllResult = this.#fnOpts.beforeAll.call(this, mode)
428416
assert(
429417
!isPromiseLike(beforeAllResult),
430418
'`beforeAll` function must be sync when using `runSync()`'
431419
)
432-
} catch (error) {
433-
return { error: toError(error) }
434420
}
435-
}
436421

437-
let totalTime = 0
438-
const samples: number[] = []
422+
let totalTime = 0
423+
const samples: number[] = []
439424

440-
const benchmarkTask = () => {
441-
if (this.#aborted) {
442-
return
443-
}
444-
try {
445-
if (this.#fnOpts.beforeEach) {
446-
const beforeEachResult = this.#fnOpts.beforeEach.call(this, mode)
447-
assert(
448-
!isPromiseLike(beforeEachResult),
449-
'`beforeEach` function must be sync when using `runSync()`'
450-
)
425+
const benchmarkTask = () => {
426+
if (this.#aborted) {
427+
return
451428
}
452-
453-
const taskTime = this.#measureSync()
454-
455-
samples.push(taskTime)
456-
totalTime += taskTime
457-
} finally {
458-
if (this.#fnOpts.afterEach) {
459-
const afterEachResult = this.#fnOpts.afterEach.call(this, mode)
460-
assert(
461-
!isPromiseLike(afterEachResult),
462-
'`afterEach` function must be sync when using `runSync()`'
463-
)
429+
try {
430+
if (this.#fnOpts.beforeEach) {
431+
const beforeEachResult = this.#fnOpts.beforeEach.call(this, mode)
432+
assert(
433+
!isPromiseLike(beforeEachResult),
434+
'`beforeEach` function must be sync when using `runSync()`'
435+
)
436+
}
437+
438+
const taskTime = this.#measureSync()
439+
440+
samples.push(taskTime)
441+
totalTime += taskTime
442+
} finally {
443+
if (this.#fnOpts.afterEach) {
444+
const afterEachResult = this.#fnOpts.afterEach.call(this, mode)
445+
assert(
446+
!isPromiseLike(afterEachResult),
447+
'`afterEach` function must be sync when using `runSync()`'
448+
)
449+
}
464450
}
465451
}
466-
}
467452

468-
try {
469453
while (
470454
// eslint-disable-next-line no-unmodified-loop-condition
471455
(totalTime < time || samples.length < iterations) &&
472456
!this.#aborted
473457
) {
474458
benchmarkTask()
475459
}
476-
} catch (error) {
477-
return { error: toError(error) }
478-
}
479460

480-
if (this.#fnOpts.afterAll) {
481-
try {
461+
if (this.#fnOpts.afterAll) {
482462
const afterAllResult = this.#fnOpts.afterAll.call(this, mode)
483463
assert(
484464
!isPromiseLike(afterAllResult),
485465
'`afterAll` function must be sync when using `runSync()`'
486466
)
487-
} catch (error) {
488-
return { error: toError(error) }
489467
}
468+
return isValidSamples(samples) ? { samples } : {}
469+
} catch (error) {
470+
return { error: toError(error) }
490471
}
491-
return isValidSamples(samples) ? { samples } : {}
492472
}
493473

494474
/**
@@ -585,7 +565,7 @@ export class Task extends EventTarget {
585565

586566
sortSamples(latencySamples)
587567

588-
const latencyStatistics = getStatisticsSorted(latencySamples, this.#retainSamples)
568+
const latencyStatistics = computeStatistics(latencySamples, this.#retainSamples)
589569
const latencyStatisticsMean = latencyStatistics.mean
590570

591571
let totalTime = 0
@@ -603,7 +583,7 @@ export class Task extends EventTarget {
603583
}
604584

605585
sortSamples(throughputSamples)
606-
const throughputStatistics = getStatisticsSorted(throughputSamples, this.#retainSamples)
586+
const throughputStatistics = computeStatistics(throughputSamples, this.#retainSamples)
607587

608588
/* eslint-disable perfectionist/sort-objects */
609589
this.#result = {

src/utils.ts

Lines changed: 14 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -164,9 +164,9 @@ export const formatNumber = (
164164
significantDigits = 5,
165165
maxFractionDigits = 2
166166
): string => {
167-
if (value === Number.POSITIVE_INFINITY) return '+∞'
168-
if (value === Number.NEGATIVE_INFINITY) return '-∞'
169-
if (Number.isNaN(value)) return 'NaN'
167+
if (value === Infinity) return '+∞'
168+
if (value === -Infinity) return '-∞'
169+
if (value !== value) return 'NaN' // eslint-disable-line no-self-compare
170170

171171
const absValue = Math.abs(value)
172172

@@ -413,15 +413,14 @@ export function absoluteDeviationMedian (
413413
* @param retainSamples - whether to keep the samples in the statistics
414414
* @returns the statistics of the sample
415415
*/
416-
export function getStatisticsSorted (samples: SortedSamples, retainSamples = false): Statistics {
416+
export function computeStatistics (samples: SortedSamples, retainSamples = false): Statistics {
417417
const { mean, vr } = meanAndVariance(samples)
418418
const sd = Math.sqrt(vr)
419419
const sem = sd / Math.sqrt(samples.length)
420420
const df = samples.length - 1
421421
const critical = tTable[df || 1] ?? tTable[0]
422422
const moe = sem * critical
423-
const absMean = Math.abs(mean)
424-
const rme = absMean === 0 ? Number.POSITIVE_INFINITY : (moe / absMean) * 100
423+
const rme = mean === 0 ? Number.POSITIVE_INFINITY : (moe / Math.abs(mean)) * 100
425424
const p50 = quantileSorted(samples, 0.5)
426425

427426
return {
@@ -503,8 +502,8 @@ export const defaultConvertTaskResultForConsoleTable: ConsoleTableConverter = (
503502
'Task name': task.name,
504503
...(state === 'aborted-with-statistics' || state === 'completed'
505504
? {
506-
'Latency avg (ns)': `${formatNumber(mToNs(task.result.latency.mean), 5, 2)} \xb1 ${task.result.latency.rme.toFixed(2)}%`,
507-
'Latency med (ns)': `${formatNumber(mToNs(task.result.latency.p50), 5, 2)} \xb1 ${formatNumber(mToNs(task.result.latency.mad), 5, 2)}`,
505+
'Latency avg (ns)': `${formatNumber(mToNs(task.result.latency.mean))} \xb1 ${task.result.latency.rme.toFixed(2)}%`,
506+
'Latency med (ns)': `${formatNumber(mToNs(task.result.latency.p50))} \xb1 ${formatNumber(mToNs(task.result.latency.mad))}`,
508507
'Throughput avg (ops/s)': `${Math.round(task.result.throughput.mean).toString()} \xb1 ${task.result.throughput.rme.toFixed(2)}%`,
509508
'Throughput med (ops/s)': `${Math.round(task.result.throughput.p50).toString()} \xb1 ${Math.round(task.result.throughput.mad).toString()}`,
510509
Samples: task.result.latency.samplesCount,
@@ -635,7 +634,7 @@ export const withConcurrency = async <R>(
635634
await Promise.allSettled(promises)
636635

637636
if (errors.length === 0) return results
638-
if (errors.length === 1) throw toError(errors[0])
637+
if (errors.length === 1) throw errors[0] // eslint-disable-line @typescript-eslint/only-throw-error
639638
throw new AggregateError(
640639
errors,
641640
'Multiple errors occurred during concurrent execution'
@@ -663,25 +662,12 @@ export const performanceNowTimestampProvider: TimestampProvider = {
663662
* Returns the current timestamp in nanoseconds using `process.hrtime.bigint()`.
664663
* @returns the current timestamp in nanoseconds
665664
*/
666-
const hrtimeBigint =
667-
typeof (globalThis as { process?: { hrtime?: { bigint: () => bigint } } })
668-
.process?.hrtime?.bigint === 'function'
669-
? (
670-
globalThis as unknown as {
671-
process: { hrtime: { bigint: () => bigint } }
672-
}
673-
).process.hrtime.bigint.bind(
674-
(
675-
globalThis as unknown as {
676-
process: { hrtime: { bigint: () => bigint } }
677-
}
678-
).process.hrtime
679-
)
680-
: () => {
681-
throw new Error(
682-
'hrtime.bigint() is not supported in this JS environment'
683-
)
684-
}
665+
const hrtimeBigint = globalThis.process?.hrtime?.bigint.bind(globalThis.process?.hrtime) ?? // eslint-disable-line @typescript-eslint/no-unnecessary-condition
666+
(() => {
667+
throw new Error(
668+
'hrtime.bigint() is not supported in this JS environment'
669+
)
670+
})
685671
/* eslint-enable jsdoc/require-returns-check */
686672

687673
/**

0 commit comments

Comments
 (0)