tinybench

中文文档
6.2.3发布于 2026/11/01MITTypeScriptES Module零依赖构建来源已验证近 30 天下载 4.6亿

简单,小而轻重的基准库!

中文使用文档
文档目录29 节
  1. 安装
  2. 使用量
  3. 文档
  4. 财务问题
  5. Bench
  6. Task
  7. TaskResult
  8. Events
  9. BenchEvent
  10. 同步检测
  11. 货币
  12. 转换任务结果 console.table()
  13. 保留样本
  14. 时间戳提供商
  15. 超头修正
  16. 任务计量
  17. 每一样本持续时间( overriddenDuration (中文(简体) )
  18. 重置费用( overriddenIterationCost (中文(简体) )
  19. 定时诊断
  20. 中止基准
  21. 座椅级中止
  22. 任务级别中止
  23. 执行期间中止
  24. 中止事件
  25. 前作艺术
  26. 作者数
  27. 贷项
  28. 捐款
  29. 发起人

小贝恩克

CI NPM version Discord neostandard Javascript Code Style

一个简单、小而轻巧的基准库! 您可以在多个 JavaScript 运行时运行基准, Tinybench 完全基于 Web API, 并使用适当的时间 process.hrtime 或者说 performance.now。 。 。 .

  • 基于环境的准确和准确的时间
  • 统计分析延迟和通量值:标准偏差,出错幅度,相差,百分位等.
  • 货币支持
  • Event 财务报告和审定财务报表 EventTarget 兼容事件
  • 无依赖关系

如果你需要更小的图书馆 比如小池或小池,请考虑提交 RFC (RFC ) (法语)

安装

$ npm install -D tinybench

使用量

你可以通过即时设定基准 Bench 分类并添加基准任务.

import { Bench } from 'tinybench'

const bench = new Bench({ name: 'simple benchmark', time: 100 })

bench
  .add('faster task', () => {
    console.log('I am faster')
  })
  .add('slower task', async () => {
    await new Promise(resolve => setTimeout(resolve, 1)) // we wait 1ms :)
    console.log('I am slower')
  })

await bench.run()

console.log(bench.name)
console.table(bench.table())

// Output:
// simple benchmark
// ┌─────────┬───────────────┬───────────────────┬───────────────────────┬────────────────────────┬────────────────────────┬─────────┐
// │ (index) │ Task name     │ Latency avg (ns)  │ Latency med (ns)      │ Throughput avg (ops/s) │ Throughput med (ops/s) │ Samples │
// ├─────────┼───────────────┼───────────────────┼───────────────────────┼────────────────────────┼────────────────────────┼─────────┤
// │ 0       │ 'faster task' │ '63768 ± 4.02%'   │ '58954 ± 15255.00'    │ '18562 ± 1.67%'        │ '16962 ± 4849'         │ 1569    │
// │ 1       │ 'slower task' │ '1542543 ± 7.14%' │ '1652502 ± 167851.00' │ '808 ± 19.65%'         │ '605 ± 67'             │ 65      │
// └─────────┴───────────────┴───────────────────┴───────────────────────┴────────────────────────┴────────────────────────┴─────────┘

这个 add 方法接受任务名称和任务函数,从而可以基准 这个! 这种方法返回引用到法官案例,所以有可能 用它来创造另一个任务,例如.

注意任务名称在某种情况下应该总是独一无二, 因为 Tinybench 存储基于任务 他们的名字在一个 Map。 。 。 .

还注意到 tinybench 默认不记录任何结果。 你可以提取相关数据 从 bench.tasks 或运行基准后的任何其他 API,并任意处理.

可在 实例 目录.

文档

财务问题

Bench

Task

TaskResult

Events

两者 Task 财务报告和审定财务报表 Bench 类扩展 EventTarget 对象。 因此,您可以使用通用 addEventListener 财务报告和审定财务报表 removeEventListener 方法。 。 .

BenchEvents

// runs on each benchmark task's cycle
bench.addEventListener('cycle', (evt) => {
  const task = evt.task;
});

// runs when timer saturation is detected for a task's measured samples
bench.addEventListener('warning', (evt) => {
  const task = evt.task;
  const reason = evt.reason; // 'zero-dominated' | 'low-distinct' | 'zero-mad'
});

TaskEvents

// runs only on this benchmark task's cycle
task.addEventListener('cycle', (evt) => {
  const task = evt.task;
});

BenchEvent

同步检测

Tinybench 自动检测任务函数是否同步 检查是否提供了函数 AsyncFunction 或者它返回一个 Promise,通过一次调用提供的函数.

您也可以明确设置 async 选项到 true 或者说 false 添加时 任务,从而避免被检测。 设定 async: false 只为了一个真正的 同步任务; 测量返回 a 函数的同步成本 Promise,通过 overriddenDuration 相反(见 任务计量) (中文(简体) ).

const bench = new Bench()

bench.add('asyncTask', async () => {}, { async: true })

bench.add('syncTask', () => {}, { async: false })

bench.add(
  'syncTaskReturningPromiseAsAsync',
  () => {
    return Promise.resolve()
  },
  { async: true }
)

await bench.run()

货币

  • 何时 mode 设置为 null (默认),货币被禁用.
  • 何时 mode 设置为“任务”,每个任务的迭代(调用任务函数)同时运行.
  • 何时 mode 设置为“ 下” , 不同的任务同时运行 。 同时循环.
const bench = new Bench({
  concurrency: 'task', // The concurrency mode to determine how tasks are run.
  threshold: 10, // Maximum concurrent iterations within a task. Defaults to Infinity.
})
await bench.run()

与 concurrency: null 或者说 'bench',每个任务都会持续到两个时间 符合预算和最低重迭数。 与 concurrency: 'task', (中文(简体) ), 在达到正限时停止排期; threshold 限制该任务内同时重复而不是同时重复 基准任务。 取消重复限制 iterations: 0 需求 限定值 threshold (例如, threshold: 10),而不是默认值 Infinity这些规则也适用于: warmupTime 财务报告和审定财务报表 warmupIterations 内 warmup()。 。 。 . Task.warmupSync() 总是使用顺序规则,不管 的货币.

转换任务结果 console.table()

您可以将基准结果转换为适合 console.table() 使用 bench.table() 方法.

const table = bench.table()
console.table(table)

您也可以通过向表格提供转换函数来自定义表格输出 table 方法.

import { Bench, type ConsoleTableConverter, formatNumber, mToNs, type Task } from 'tinybench'

/**
 * The default converter function for console.table output.
 * Modify it as needed to customize the table format.
 */
const defaultConverter: ConsoleTableConverter = (task: Task): Record<string, number | string> => {
  const state = task.result.state
  return {
    'Task name': task.name,
    ...(state === 'aborted-with-statistics' || state === 'completed'
      ? {
          'Latency avg (ns)': `${formatNumber(mToNs(task.result.latency.mean))} \xb1 ${formatNumber(task.result.latency.rme)}%`,
          'Latency med (ns)': `${formatNumber(mToNs(task.result.latency.p50))} \xb1 ${formatNumber(mToNs(task.result.latency.mad))}`,
          'Throughput avg (ops/s)': `${Math.round(task.result.throughput.mean).toString()} \xb1 ${formatNumber(task.result.throughput.rme)}%`,
          'Throughput med (ops/s)': `${Math.round(task.result.throughput.p50).toString()} \xb1 ${Math.round(task.result.throughput.mad).toString()}`,
          Samples: task.result.latency.samplesCount,
        }
      : state !== 'errored'
        ? {
            'Latency avg (ns)': 'N/A',
            'Latency med (ns)': 'N/A',
            'Throughput avg (ops/s)': 'N/A',
            'Throughput med (ops/s)': 'N/A',
            Samples: 'N/A',
            Remarks: state,
          }
        : {
            Error: task.result.error.message,
            Stack: task.result.error.stack ?? 'N/A',
          }),
    ...(state === 'aborted-with-statistics' && {
      Remarks: state,
    }),
  }
}

const bench = new Bench({ name: 'custom table benchmark', time: 100 })
// add tasks...

console.table(bench.table(defaultConverter))

保留样本

默认情况下, Tinybench 不保存样本 latency 财务报告和审定财务报表 throughput 改为 最小化内存使用。 需要原始样本时启用保留样本 绘图、自定义分析或输出结果.

通过设置 retainSamples 选项到 true 创建时 Bench 实例:

const bench = new Bench({ retainSamples: true })

通过设置 retainSamples 选项到 true 添加任务时 :

bench.add(
  'task with samples',
  () => {
    // Task logic here
  },
  { retainSamples: true }
)

时间戳提供商

Tinybench可以利用不同的时间戳提供商来测量时间间隔. 默认使用 performance.now()。 。 。 .

这个 timestampProvider 选项可以在创建 Bench 举个例子 这个 接受一个 TimestampProvider 普通对象或缩写 供应商 hrtimeNow 财务报告和审定财务报表 performanceNow。 。 。 .

如果您使用 bun 运行时间,您也可以使用 bunNanoseconds 缩写.

你可以设置 timestampProvider 改为 auto 让Tinybench选择最多 根据运行时间提供精确可用的时间戳 .

import { Bench } from 'tinybench'

const bench = new Bench({
  timestampProvider: 'hrtimeNow', // or 'performanceNow', 'bunNanoseconds', 'auto'
})

如果您想要提供自定义的时间戳提供者, 您可以创建执行对象 页:1 TimestampProvider 接口 :

import { Bench, type TimestampProvider } from 'tinybench'

// Custom timestamp provider using Date.now()
const dateNowTimestampProvider: TimestampProvider = {
  name: 'dateNow', // name of the provider
  fn: Date.now, // function that returns the current timestamp
  toMs: ts => Number(ts), // convert the timestamp to milliseconds
  fromMs: ts => ts, // convert milliseconds to the format used by fn()
}

const bench = new Bench({
  timestampProvider: dateNowTimestampProvider,
})

您也可以设置 now 选项到返回当前时间戳的函数. 将改为 TimestampProvider 内部.

import { Bench } from 'tinybench'

const bench = new Bench({
  now: Date.now,
})

超头修正

每个计时器呼叫( E)performance.now(), (中文(简体) ), process.hrtime.bigint()拥有一个 非零呼叫费用 C。用于一个任务,其真正持续时间 X 可比较 改为 C,原始测量样本 X + C 以计时器为主 而不是任务.

何时 subtractTimerOverhead: true 设置, 一个估计数 Ĉ 计算 施工时间一次通过 calibrateTimerOverhead, (中文(简体) ), 财务报告和审定财务报表 Math.max(0, raw_sample - Ĉ) 用作每个非重叠样本 在计算统计数据之前.

const bench = new Bench({ subtractTimerOverhead: true })
console.log(bench.timerOverhead) // calibrated Ĉ in ms (or undefined)

校正辅助器也出口给直接使用,其中 可配置的估算战略'median' 默认,或 'min' 编号 : 'p05':

import { calibrateTimerOverhead, hrtimeNowTimestampProvider } from 'tinybench'

const overhead = calibrateTimerOverhead(hrtimeNowTimestampProvider, {
  estimator: 'p05',
  pairs: 1024,
  warmupPairs: 64,
})

出出洞来.

  • 与 concurrency: 'task' - 管理费用经过校正 按顺序排列,不反映同时执行费用. 建筑业(和 run()如果两者都设定了,则投掷.
  • 用于次级项目测量X ≈ Ĉ(b) 与《京都议定书》 max(0, …) 夹子 截取下尾和偏差统计; 偏好 overriddenDuration。 。 。 .
  • 当计时器过于粗糙,无法解决呼叫费用时——不到一半 校正对对产生正三角洲(呼叫成本) C < R / 2, (中文(简体) ), 例如,a Date.now- 级计时器 >= 1 ms ——校正 返回时 0 选项变成禁用.
  • 每个样本都包含一个单一的任务调用,而不是一个分批循环,所以 每样计时器地板 C 未摊销。 这是蓄意取舍: 它产生真实的每个样本分布(百分比、MAD、饱和度) 以较高分公司为代价C 噪音地板。 用于以下工作 计时器谷物, 使用 overriddenDuration。 。 。 .
  • Ĉ 不覆盖同步任务的 await 微任务转弯——即: 在所测量的窗口内,但没有校正对——所以 亚微秒样本即使与 subtractTimerOverhead。 。 。 . 使用 overriddenDuration 用于这种分解工作.

任务计量

每一样本持续时间(overriddenDuration(中文(简体) )

任务函数可能返回包含 overriddenDuration (以毫秒计). 该值被记录在计时器测量样本的外: 定时器仍然将任务函数置于括号内,但其测量是 已丢弃,未对替换的间接费用校正 数值。 用于外部定时工作或次级管理项目测量 计时器无法解决.

import type { FnReturnedObject } from 'tinybench'

bench.add('externally-timed', (): FnReturnedObject => {
  const start = process.hrtime.bigint()
  doWork()
  const elapsedMs = Number(process.hrtime.bigint() - start) / 1e6
  return { overriddenDuration: elapsedMs }
})

过时的样本不包括在 Task.detectedResolution 财务报告和审定财务报表 从计时器饱和度检测.

重置费用(overriddenIterationCost(中文(简体) )

当一次重复数次内调时,每调值值你 想要在统计中与重复的实际成本不同 页:1 time 编号 : warmupTime 预算。 返回时 overriddenIterationCost (ms) 宣布整个迭代的壁时成本:

import type { FnReturnedObject } from 'tinybench'

bench.add('batched', () => {
  const innerCalls = 100
  const start = process.hrtime.bigint()
  for (let i = 0; i < innerCalls; i++) parse(input)
  const elapsedMs = Number(process.hrtime.bigint() - start) / 1e6
  return {
    overriddenDuration: elapsedMs / innerCalls, // mean per call in this batch
    overriddenIterationCost: elapsedMs, // budget cost of the iteration
  } satisfies FnReturnedObject
})

每个样本是每批呼叫的平均持续时间。 百分比和百分比 分散描述这些批次手段,而不是批次中个别的呼叫.

语义:

  • 样本使用有效的 overriddenDuration,否则计时器测量 持续时间。 顺序预算使用有效的 overriddenIterationCost, (中文(简体) ), 否则,在定时器 -- -- 超头修正之前,样本。 仅返回 overriddenDuration 因此,保持历史行为.
  • 任务当前 run() 财务报告和审定财务报表 warmup() 使用真实的时钟进行预算 不检查 overriddenIterationCost (既无存在也无价值). 每项任务的费用 concurrency: 'bench' 内 Task.warmupSync() 无论币种如何.
  • 两个字段的验证方法相同(无限数字为 ^ 0, -0 包含);无效值被视为不存在.
  • 成本领域必须报告为 in 运算符(拥有或拥有) 页:1 缺出密钥的代理默认不是宣布的成本 。 错误 在检查或读取此字段时,则被视为一笔没有的费用.
  • 费用不影响定时器-管理头修正或定时器诊断; 它们在样本上运作. result.totalTime 财务报告和审定财务报表 period 仍为 样本来源。 仅返回成本 留下的样本计时器, 因此,计时器饱和度警告仍然会发生.
  • 申报的费用没有根据实际情况加以核实: 墙上小时成本是 C 但宣布为 O 运行到大约 time × C / O 何时 O < C,并缩短当 O > C备注 时间预算支配着最小重迭数.
  • 警告,我马上回来. 重复费用 0 (或 -0无法满足正数 相接的时间预算;微小的正成本可能使达到不切实际. 与 time: 0,运行可以在最小重迭数完成。 一样 规则适用于热身。 从外部定时器取消需要生成 切换到事件循环,不能中断 runSync(); 见 执行期间中止。 。 。 .

定时诊断

之后 bench.run() (或 runSync()),每个任务都会暴露 detectedResolution:至少发生最小的阳性耐久性样本 两次,如果没有重复,则为最小的正样本。 只有计时器 考虑在任何高层修正之后的样本;如果无正面的, 结果 undefined。这是基于样本的热力学,不是保证 绑定在计时器的分辨率.

const task = bench.getTask('foo')
console.log(task?.detectedResolution) // e.g. 0.000041 (≈ 41 ns)

至少有10个这样的样本,小箱发送a 'warning' 活动 任务和板凳,如果超过一半为零,则少于 max(3, min(10, ⌊n / 1000⌋)) 出现差异值,或 MAD 为 0, 与 n > 100。该事件带有匹配 TimerSaturationReason数字 :

bench.addEventListener('warning', evt => {
  console.warn(`timer-saturated: ${evt.task?.name} — ${evt.reason}`)
})

同样的高压和估测器被曝光为独立的助手 自定义分析 : detectTimerSaturation, (中文(简体) ), classifyTimerSaturation, (中文(简体) ), 财务报告和审定财务报表 estimateResolution。 。 。 .

中止基准

Tinybench 支持使用中止基准 AbortSignal 在法官一级和任务一级:

座椅级中止

将一个信号传递到 Bench 构造器 :

const controller = new AbortController()

const bench = new Bench({ signal: controller.signal })

bench
  .add('task1', () => {
    // This will be aborted
  })
  .add('task2', () => {
    // This will also be aborted
  })

// Abort all tasks
controller.abort()

await bench.run()
// Both tasks will be aborted

任务级别中止

通过向任务选项传递信号中止单个任务而不影响其他任务:

const controller = new AbortController()

const bench = new Bench()

bench
  .add(
    'abortable task',
    () => {
      // This task can be aborted independently
    },
    { signal: controller.signal }
  )
  .add('normal task', () => {
    // This task will continue normally
  })

// Abort only the first task
controller.abort()

await bench.run()
// Only 'abortable task' will be aborted, 'normal task' continues

执行期间中止

你可以中止基准 当它们运行时:

const controller = new AbortController()

const bench = new Bench({ time: 10000 }) // Long-running benchmark

bench.add(
  'long task',
  async () => {
    await new Promise(resolve => setTimeout(resolve, 100))
  },
  { signal: controller.signal }
)

// Abort after 1 second
setTimeout(() => controller.abort(), 1000)

await bench.run()
// Task will stop after ~1 second instead of running for 10 seconds

计时器触发取消需要任务或钩子向 事件循环,例如等待 I/O。 等待一个已经解开的承诺 这还不够。 单位 runSync(),任务或同步钩可以调用 controller.abort() ,但外部计时器 不能中断运行.

中止事件

两者 Bench 财务报告和审定财务报表 Task 发射 abort 中止时的事件 :

const controller = new AbortController()
const bench = new Bench()

bench.add(
  'task',
  () => {
    // Task function
  },
  { signal: controller.signal }
)

const task = bench.getTask('task')
if (!task) {
  throw new Error('Task not found')
}

// Listen for abort events
task.addEventListener('abort', () => {
  console.log('Task aborted!')
})

bench.addEventListener('abort', () => {
  console.log('Bench received abort event!')
})

controller.abort()
await bench.run()

说明: 已中止的任务 task.result.state 等于 'aborted' 或者说 'aborted-with-statistics'。已在进行的重复可能在此之前完成 运行返回.

前作艺术

作者数


穆罕默德·巴盖尔

贷项


乌兹洛帕克

波约

捐款

请随意为项目创造问题/讨论,然后是公关!

发起人

你的赞助能对我们继续开放源码的工作产生巨大影响!

版本与发布记录

tinybench 共发布 71 个版本,首次发布于 2022/04/29;过去 12 个月发布了 19 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
6.2.3latest2026/11/014 天前
6.2.22026/10/1126 天前
6.2.12026/10/0730 天前
6.2.02026/09/101 个月前
6.1.62026/09/052 个月前
6.1.52026/09/042 个月前

其他发布通道:beta → 6.0.0-beta.4,next → 6.0.0-rc.1。

关于 tinybench 的常见问题

tinybench 是什么?

简单,小而轻重的基准库!

如何安装 tinybench?

在项目目录运行 npm install tinybench,或使用 pnpm add / yarn add / bun add。

tinybench 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

tinybench 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

tinybench 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

tinybench 可以商用吗?

tinybench 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

tinybench 的下载量有多少?

根据 npm 官方下载统计,tinybench 在 2026/10/05 – 2026/11/03 这 30 天内被下载 464,255,336 次,日均约 15,475,178 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

tinybench 还在维护吗?

最新版本 6.2.3 发布于 2026/11/01(4 天前);至今共发布 71 个版本,其中过去 12 个月发布了 19 个;首次发布于 2022/04/29。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。