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

156104157105

Tinybench 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

198146

await 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

202208203209

By 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

224282225283

Tinybench supports aborting benchmarks using `AbortSignal` at both the bench and task levels: