feat: export formatNumber, add documentation for converting the resul… · tinylibs/tinybench@37b78db
@@ -100,58 +100,6 @@ task.addEventListener('cycle', (evt) => {
100100101101### [`BenchEvent`](https://tinylibs.github.io/tinybench/types/BenchEvent.html)
102102103-## Timestamp Providers
104-105-Tinybench can utilize different timestamp providers for measuring time intervals.
106-By default it uses `performance.now()`.
107-108-The `timestampProvider` option can be set when creating a `Bench` instance. It
109-accepts either a `TimestampProvider` object or shorthands for the common
110-providers `hrtimeNow` and `performanceNow`.
111-112-If you use `bun` runtime, you can also use `bunNanoseconds` shorthand.
113-114-You can set the `timestampProvider` to `auto` to let Tinybench choose the most
115-precise available timestamp provider based on the runtime.
116-117-```ts
118-import { Bench } from 'tinybench'
119-120-const bench = new Bench({
121- timestampProvider: 'hrtimeNow' // or 'performanceNow', 'bunNanoseconds', 'auto'
122-})
123-```
124-125-If you want to provide a custom timestamp provider, you can create an object that implements
126-the `TimestampProvider` interface:
127-128-```ts
129-import { Bench, TimestampProvider } from 'tinybench'
130-131-// Custom timestamp provider using Date.now()
132-const dateNowTimestampProvider: TimestampProvider = {
133- name: 'dateNow', // name of the provider
134- fn: Date.now, // function that returns the current timestamp
135-toMs: ts => ts, // convert the timestamp to milliseconds
136-fromMs: ts => ts // convert milliseconds to the format used by fn()
137-}
138-139-const bench = new Bench({
140- timestampProvider: dateNowTimestampProvider
141-})
142-```
143-144-You can also set the `now` option to a function that returns the current timestamp.
145-It will be converted to a `TimestampProvider` internally.
146-147-```ts
148-import { Bench } from 'tinybench'
149-150-const bench = new Bench({
151- now: Date.now
152-})
153-```
154-155103## Async Detection
156104157105Tinybench automatically detects if a task function is asynchronous by
@@ -198,6 +146,64 @@ bench.concurrency = 'task' // The concurrency mode to determine how tasks are ru
198146await bench.run()
199147```
200148149+## Convert task results for `console.table()`
150+151+You can convert the benchmark results to a table format suitable for
152+`console.table()` using the `bench.table()` method.
153+154+```ts
155+const table = bench.table()
156+console.table(table)
157+```
158+159+You can also customize the table output by providing a convert-function to the `table` method.
160+161+```ts
162+import { Bench, type ConsoleTableConverter, formatNumber, mToNs, type Task } from 'tinybench'
163+164+/**
165+ * The default converter function for console.table output.
166+ * Modify it as needed to customize the table format.
167+ */
168+const defaultConverter: ConsoleTableConverter = (
169+task: Task
170+): Record<string, number | string> => {
171+const state = task.result.state
172+return {
173+'Task name': task.name,
174+...(state === 'aborted-with-statistics' || state === 'completed'
175+? {
176+'Latency avg (ns)': `${formatNumber(mToNs(task.result.latency.mean))} \xb1 ${task.result.latency.rme.toFixed(2)}%`,
177+'Latency med (ns)': `${formatNumber(mToNs(task.result.latency.p50))} \xb1 ${formatNumber(mToNs(task.result.latency.mad))}`,
178+'Throughput avg (ops/s)': `${Math.round(task.result.throughput.mean).toString()} \xb1 ${task.result.throughput.rme.toFixed(2)}%`,
179+'Throughput med (ops/s)': `${Math.round(task.result.throughput.p50).toString()} \xb1 ${Math.round(task.result.throughput.mad).toString()}`,
180+ Samples: task.result.latency.samplesCount,
181+ }
182+: state !== 'errored'
183+? {
184+'Latency avg (ns)': 'N/A',
185+'Latency med (ns)': 'N/A',
186+'Throughput avg (ops/s)': 'N/A',
187+'Throughput med (ops/s)': 'N/A',
188+ Samples: 'N/A',
189+ Remarks: state,
190+ }
191+: {
192+ Error: task.result.error.message,
193+ Stack: task.result.error.stack ?? 'N/A',
194+ }),
195+...(state === 'aborted-with-statistics' && {
196+ Remarks: state,
197+ }),
198+ }
199+}
200+201+const bench = new Bench({ name: 'custom table benchmark', time: 100 })
202+// add tasks...
203+204+console.table(bench.table(defaultConverter))
205+```
206+201207## Retaining Samples
202208203209By default Tinybench does not keep the samples for `latency` and `throughput` to
@@ -220,6 +226,58 @@ bench.add('task with samples', () => {
220226}, { retainSamples: true })
221227```
222228229+## Timestamp Providers
230+231+Tinybench can utilize different timestamp providers for measuring time intervals.
232+By default it uses `performance.now()`.
233+234+The `timestampProvider` option can be set when creating a `Bench` instance. It
235+accepts either a `TimestampProvider` object or shorthands for the common
236+providers `hrtimeNow` and `performanceNow`.
237+238+If you use `bun` runtime, you can also use `bunNanoseconds` shorthand.
239+240+You can set the `timestampProvider` to `auto` to let Tinybench choose the most
241+precise available timestamp provider based on the runtime.
242+243+```ts
244+import { Bench } from 'tinybench'
245+246+const bench = new Bench({
247+ timestampProvider: 'hrtimeNow' // or 'performanceNow', 'bunNanoseconds', 'auto'
248+})
249+```
250+251+If you want to provide a custom timestamp provider, you can create an object that implements
252+the `TimestampProvider` interface:
253+254+```ts
255+import { Bench, TimestampProvider } from 'tinybench'
256+257+// Custom timestamp provider using Date.now()
258+const dateNowTimestampProvider: TimestampProvider = {
259+ name: 'dateNow', // name of the provider
260+ fn: Date.now, // function that returns the current timestamp
261+toMs: ts => ts, // convert the timestamp to milliseconds
262+fromMs: ts => ts // convert milliseconds to the format used by fn()
263+}
264+265+const bench = new Bench({
266+ timestampProvider: dateNowTimestampProvider
267+})
268+```
269+270+You can also set the `now` option to a function that returns the current timestamp.
271+It will be converted to a `TimestampProvider` internally.
272+273+```ts
274+import { Bench } from 'tinybench'
275+276+const bench = new Bench({
277+ now: Date.now
278+})
279+```
280+223281## Aborting Benchmarks
224282225283Tinybench supports aborting benchmarks using `AbortSignal` at both the bench and task levels: