Skip to content

Commit 366cf99

Browse files
pallospjerome-benoit
andauthoredJan 29, 2025··
feat: improve the latency and throughput formatting in the result table (#233)
Co-authored-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
1 parent 7bcc8c0 commit 366cf99

File tree

3 files changed

+49
-3
lines changed

3 files changed

+49
-3
lines changed
 

‎src/bench.ts

+4-3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
import { createBenchEvent } from './event'
2222
import { Task } from './task'
2323
import {
24+
formatNumber,
2425
invariant,
2526
type JSRuntime,
2627
mToNs,
@@ -254,12 +255,12 @@ export class Bench extends EventTarget {
254255
}
255256
: (convert?.(task) ?? {
256257
'Task name': task.name,
257-
'Latency average (ns)': `${mToNs(task.result.latency.mean).toFixed(2)} \xb1 ${task.result.latency.rme.toFixed(2)}%`,
258+
'Latency average (ns)': `${formatNumber(mToNs(task.result.latency.mean), 5, 2)} \xb1 ${task.result.latency.rme.toFixed(2)}%`,
258259
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
259-
'Latency median (ns)': `${mToNs(task.result.latency.p50!).toFixed(2)}${Number.parseFloat(mToNs(task.result.latency.mad!).toFixed(2)) > 0 ? ` \xb1 ${mToNs(task.result.latency.mad!).toFixed(2)}` : ''}`,
260+
'Latency median (ns)': `${formatNumber(mToNs(task.result.latency.p50!), 5, 2)} \xb1 ${mToNs(task.result.latency.mad!).toFixed(2)}`,
260261
'Throughput average (ops/s)': `${task.result.throughput.mean.toFixed(0)} \xb1 ${task.result.throughput.rme.toFixed(2)}%`,
261262
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
262-
'Throughput median (ops/s)': `${task.result.throughput.p50!.toFixed(0)}${Number.parseInt(task.result.throughput.mad!.toFixed(0), 10) > 0 ? ` \xb1 ${task.result.throughput.mad!.toFixed(0)}` : ''}`,
263+
'Throughput median (ops/s)': `{Math.round(task.result.throughput.p50!)} \xb1 ${Math.round(task.result.throughput.mad)}`,
263264
Samples: task.result.latency.samples.length,
264265
})
265266
/* eslint-enable perfectionist/sort-objects */

‎src/utils.ts

+23
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,29 @@ export const nToMs = (ns: number) => ns / 1e6
135135
*/
136136
export const mToNs = (ms: number) => ms * 1e6
137137

138+
/**
139+
* @param x number to format
140+
* @param targetDigits number of digits in the output to aim for
141+
* @param maxFractionDigits hard limit for the number of digits after the decimal dot
142+
* @returns formatted number
143+
*/
144+
export const formatNumber = (x: number, targetDigits: number, maxFractionDigits: number): string => {
145+
// Round large numbers to integers, but not to multiples of 10.
146+
// The actual number of significant digits may be more than `targetDigits`.
147+
if (Math.abs(x) >= 10 ** targetDigits) {
148+
return x.toFixed()
149+
}
150+
151+
// Round small numbers to have `maxFractionDigits` digits after the decimal dot.
152+
// The actual number of significant digits may be less than `targetDigits`.
153+
if (Math.abs(x) < 10 ** (targetDigits - maxFractionDigits)) {
154+
return x.toFixed(maxFractionDigits)
155+
}
156+
157+
// Round medium magnitude numbers to have exactly `targetDigits` significant digits.
158+
return x.toPrecision(targetDigits)
159+
}
160+
138161
let hrtimeBigint: () => bigint
139162
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access
140163
if (typeof (globalThis as any).process?.hrtime?.bigint === 'function') {

‎test/utils.test.ts

+22
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,28 @@
11
import { expect, test } from 'vitest'
22

33
import { getStatisticsSorted } from '../src/utils'
4+
import { formatNumber } from '../src/utils'
5+
6+
7+
test('formatting integers', () => {
8+
expect(formatNumber(123456, 5, 2)).toBe('123456')
9+
expect(formatNumber(12345, 5, 2)).toBe('12345')
10+
expect(formatNumber(1234, 5, 2)).toBe('1234.0')
11+
expect(formatNumber(123, 5, 2)).toBe('123.00')
12+
expect(formatNumber(12, 5, 2)).toBe('12.00')
13+
expect(formatNumber(1, 5, 2)).toBe('1.00')
14+
expect(formatNumber(0, 5, 2)).toBe('0.00')
15+
expect(formatNumber(-1, 5, 2)).toBe('-1.00')
16+
})
17+
18+
test('formatting floats', () => {
19+
expect(formatNumber(123456.789, 5, 2)).toBe('123457')
20+
expect(formatNumber(12345.6789, 5, 2)).toBe('12346')
21+
expect(formatNumber(1234.56789, 5, 2)).toBe('1234.6')
22+
expect(formatNumber(123.456789, 5, 2)).toBe('123.46')
23+
expect(formatNumber(12.3456789, 5, 2)).toBe('12.35')
24+
expect(formatNumber(-12.3456789, 5, 2)).toBe('-12.35')
25+
})
426

527
test('median absolute deviation', () => {
628
// https://www.wolframalpha.com/input?i=MedianDeviation[1,2,3]

0 commit comments

Comments
 (0)
Please sign in to comment.