Vitest benchmark 配置完全指南:从 include/exclude 到自定义 Provider 与结果持久化

发布时间:2026/11/9 23:44:54

Vitest benchmark 配置完全指南:从 include/exclude 到自定义 Provider 与结果持久化 Vitest benchmark 配置完全指南从 include/exclude 到自定义 Provider 与结果持久化【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitest导读benchmark是 Vitest 中专门用于性能基准测试Benchmarking的顶层配置块它在test配置下工作用于控制vitest bench命令的行为。通过本文你将掌握 benchmark 项目的启用机制、文件匹配规则、原始样本保留、可插拔的 Provider 架构以及如何抑制模块运行器开销警告——每个配置项都会结合 vitest/src/node/types/benchmark.ts 与 vitest/src/node/defaults.ts 中的源码默认值逐一剖析并给出可直接复制运行的配置示例。配置总览类型与默认值benchmark选项的类型为{ include?, exclude?, ... }即一个对象字段全部可选。完整的用户配置接口定义在 types/benchmark.ts所有字段的默认值集中声明在 src/defaults.ts 的benchmarkConfigDefaults中配置项类型默认值作用enabledbooleanfalse是否启用独立的 benchmark 项目includestring[][**/*.{bench,benchmark}.?(c|m)[jt]s?(x)]匹配基准测试文件的 globexcludestring[][node_modules, dist, .idea, .git, .cache]排除目录继承自测试的默认排除项includeSourcestring[][]源内基准测试文件的 globretainSamplesbooleanfalse是否在结果中保留每次迭代的samples数组providerstringundefined使用内置 provider自定义基准执行引擎模块路径suppressExportGetterWarningsbooleanfalse是否抑制导出 getter 访问过多警告projectNamestring内部字段运行时自动填充${projectName}占位符注意exclude的默认值在文档中表现为[node_modules, dist, .idea, .git, .cache]它复用了defaultExclude见 defaults.ts 的**/node_modules/**、**/.git/**同时内置了dist、.idea、.cache等构建产物与 IDE 目录的排除。benchmark.enabled独立基准测试项目开关类型boolean默认值false当设为true时Vitest 会在你的常规测试项目之外克隆出一个专用 benchmark 项目它复用父项目的 Vite 配置但使用 benchmark 专属的 include/exclude 规则、强制串行执行并将benchfixture 暴露给匹配benchmark.include的文件。运行vitest bench命令会自动启用该选项无需手动配置。从源码看这个克隆项目的机制实现在 projects/resolveProjects.ts 的expandBenchmarksInEntries函数中对每个启用了 benchmark 的项目或benchmarkOnly模式下的所有项目生成一个名为原项目名 (bench)无名字时叫bench的新项目条目并注入以下关键约束maxWorkers: 1、maxConcurrency: 1——基准测试文件之间永无并发testTimeout提升至至少 60 秒、hookTimeout提升至至少 120 秒避免长基准被误杀sequence.concurrent: false且分配独立的groupOrder——基准始终在单独的隔离分组中串行执行coverage.enabled: false、typecheck.enabled: false——基准项目不参与覆盖率与类型检查原始项目中的benchmark.enabled被重置为false确保常规vitest运行时不会把基准文件当普通测试跑。同时 core.ts 表明当 CLI 传入--benchmark即benchmarkOnly时运行前会把projects过滤为只保留config.benchmark.enabled true的 benchmark 变体项目。import { defineConfig } from vitest/config export default defineConfig({ test: { benchmark: { enabled: true, // 让 vitest 同时运行普通测试与基准测试 }, }, })启用后运行vitest普通测试先执行基准测试随后在独立隔离分组中执行——两者互不干扰基准结果不会被测试执行噪声污染。benchmark.include / benchmark.exclude文件匹配规则include类型string[]默认[**/*.{bench,benchmark}.?(c|m)[jt]s?(x)]exclude类型string[]默认[node_modules, dist, .idea, .git, .cache]include决定了哪些文件属于 benchmark 项目。默认 glob 的展开含义是匹配所有文件名形如*.bench.ts、*.benchmark.js、*.bench.mts、*.benchmark.cts、*.bench.tsx等变体的文件——即文件名以.bench或.benchmark结尾扩展名支持.js/.ts/.jsx/.tsx/.mjs/.mts/.cjs/.cts的任意组合。判定基准文件的标准是文件名而不是内容中是否使用了benchfixture。把parser.test.ts改名为parser.bench.ts或调整benchmark.include文件才会进入 benchmark 项目反之在普通测试文件中使用{ bench }会直接抛出错误。这一点由validateBenchmarkProject见 runtime/benchmark.ts 中bench工厂函数的第一步保证。exclude则给出被忽略的目录。自定义时通常写成export default defineConfig({ test: { benchmark: { include: [bench/**/*.bench.ts], exclude: [bench/legacy/**, node_modules], }, }, })benchmark.includeSource源内基准测试类型string[]默认值[]与常规配置的includeSource语义一致当定义该 glob 后所有匹配文件凡是包含import.meta.vitest代码块的都会被执行基准测试。它让基准测试可以直接写在源码文件内部例如import { bench } from vitest if (import.meta.vitest) { bench(parse in-source, () JSON.parse({a:1})).run() }export default defineConfig({ test: { benchmark: { includeSource: [src/**/*.ts], }, }, })这样源码文件即文档、即测试、即基准适合把性能基线跟实现代码放在一起维护。benchmark.retainSamples保留逐次迭代原始样本类型boolean默认值false开启后每个基准结果的samples数组每次迭代的计时会被保留下来。默认关闭以节省内存——一次基准可能运行成千上万次迭代每个样本都是一份浮点数组。当自定义 reporter 或 API 消费者需要原始样本做更精细的统计如绘制分布图、计算分位数时再开启export default defineConfig({ test: { benchmark: { retainSamples: true, }, }, })源码层面该值会被直接透传给 Tinybench 实例的retainSamples选项见 runtime/benchmark/default-provider.tsconst tinybench new Tinybench({ signal: test.context.signal, name: ${test.fullTestName} ${currentIndex}, retainSamples: config.benchmark.retainSamples, ...options, now, })benchmark.provider替换基准执行引擎类型string默认值undefined使用内置 providerbenchmark.provider指定一个模块路径该模块的 default export 必须实现BenchmarkProvider接口。相对路径从项目根目录解析。内置 provider 基于 Tinybench详见 Benchmarking 指南替换 provider 即可使用其他基准引擎或执行策略。完整的 Provider API 与生命周期说明见 Custom Benchmark Provider 指南这里摘出核心要点接口BenchmarkProvider只有一个方法run(group: BenchmarkGroup): PromiseBenchResult[]见 runtime/benchmark.ts。group包含test其context.signal在取消时 abort、config当前项目解析后的 benchmark 配置、registrations可运行的基准列表含name/fn/fnOpts与options.run()或bench.compare()传入的运行选项。职责provider 必须尊重运行选项与注册选项按引擎生命周期执行每个基准函数及其beforeAll/beforeEach/afterEach/afterAllhooks执行失败应抛出错误使测试失败。返回值run必须为每个可运行注册项返回一个BenchResult按name与注册项一一对应它同时是.run()返回值、对比表、reporter 与持久化结果的唯一数据来源。自定义引擎必须把测量结果转换为vitest导出的 Tinybench 兼容BenchResult结构。生命周期provider 模块在首次使用时导入其 default export 在worker 存活期间被缓存见 runtime/benchmark.ts 的resolveBenchmarkProviderAPI 没有独立的 setup/teardown hooks需要 worker 级状态时直接挂在 provider 对象上。特殊规则bench.from()创建的注册项由 Vitest 自行加载结果不会传给 providerloadProviderModuleruntime/benchmark.ts会在模块无 default export 时抛出明确错误。一个最小可用的自定义 provider封装 Tinybench如下import { defineConfig } from vitest/config export default defineConfig({ test: { benchmark: { provider: ./benchmark-provider.ts, }, }, })import type { BenchmarkProvider } from vitest import { Bench } from tinybench const provider { async run({ test, config, registrations, options }) { const bench new Bench({ signal: test.context.signal, retainSamples: config.retainSamples, ...options, }) for (const { name, fn, fnOpts } of registrations) { bench.add(name, fn, fnOpts) } await bench.run() return bench.tasks.map((task) { const result task.result if (result.state errored) { throw result.error } if (result.state ! completed) { throw new Error(Benchmark ${task.name} ended in the ${result.state} state) } return { ...result, name: task.name, } }) }, } satisfies BenchmarkProvider export default provider若在 provider 中使用 Tinybench需把它加入项目的直接依赖。benchmark.suppressExportGetterWarnings抑制导出 getter 警告类型boolean默认值false默认情况下 Vitest 通过 Vite 的模块运行器由experimental.viteModuleRunner配置在 Node.js 中运行测试该运行器会把每个模块导出都包装成 getter——每次访问导入的绑定都要经过__vite_ssr_module__.value之类的间接调用。普通测试中这点开销微不足道但基准函数被调用数百万次时getter 调用本身就可能主导测量结果详见 Module Runner Overhead。Vitest 在基准运行期间跟踪 getter 访问次数workerState.getterTracker一旦检测到过多访问就会打印警告。suppressExportGetterWarnings: true用于在以下两种场景静默该警告你有意接受了这部分开销例如只是粗略对比、不追求极致精度警告过于频繁、而该基准的 getter 开销确实可忽略。其底层逻辑见 runtime/benchmark.ts 的runGroup执行完provider.run后只有在该配置为false时才会检查getterTracker.getExcessiveInvocations()并打印黄色警告警告中会列出被过度访问的模块导出moduleId exportName。export default defineConfig({ test: { benchmark: { suppressExportGetterWarnings: true, }, }, })更好的做法不是压制警告而是消除 getter 开销在基准函数内先用局部变量缓存导入引用const _parse parse或直接基准已构建的产物通过包名导入而非../src/index.ts甚至为基准项目关闭experimental.viteModuleRunner让 Node 原生执行 ESM。与其他功能的联动配置项如何支撑基准实战benchmark配置不是孤立的开关它与vitest bench命令、benchfixture、结果持久化机制共同构成完整的基准工作流vitest bench自动启用 benchmark 项目CLI 侧 cli/cac.ts 注册了bench [...filters]子命令其 action 在 cli/cac.ts 中设置options.benchmarkOnly true随后 core.ts 据此只保留 benchmark 变体项目。支持文件名过滤器与-t/--testNamePatternvitest bench parser、vitest bench -t JSON。bench.from()读取历史结果bench.from(name, source)不执行函数而是从路径或返回数据的函数含 Promise读取已存储结果参与bench.compare()。读取失败会抛出 could not find a result file 错误见 runtime/benchmark.ts。writeResult持久化单次基准成功后把结果写入 JSON路径相对项目根目录支持${projectName}占位符做跨项目产物失败则不写。文件写入实现是 node/benchmark.ts 的BenchmarkManager.writeResult。路径安全校验BenchmarkManager.resolvenode/benchmark.ts会拒绝解析到项目根目录之外的所有路径——writeResult/bench.from()接受任意输入但绝不允许基准文件读写工作区之外的文件。跨项目对比bench.compare()内传入{ perProject: true }的基准会被额外收集到运行结束时的跨项目汇总表中每个项目读自己的${projectName}产物。小结benchmark配置块用 8 个字段精确刻画了 Vitest 的基准测试运行形态enabled决定是否克隆出独立的基准项目include/exclude/includeSource划定文件边界retainSamples控制原始样本的保留provider允许把执行引擎整个替换掉suppressExportGetterWarnings管理模块运行器开销的告警。理解这些配置与 resolveProjects.ts 中的项目克隆、runtime/benchmark.ts 中的注册/执行编排、node/benchmark.ts 中的产物读写三者之间的关系你就能把 Vitest 的基准能力真正用起来——无论是内置 Tinybench 的零配置体验还是面向特殊引擎的自定义 Provider 方案。想进一步深入可以继续阅读Benchmarking 指南——完整的基准编写、对比、断言与稳定性实践Custom Benchmark Provider——Provider 接口与生命周期详解benchmark 类型定义——所有字段的源码级注释内置 provider 实现——Tinybench 如何被封装成BenchmarkProvider。【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitest创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/10 0:14:36

基于Transformer的智能问答系统设计与实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/10 0:31:19

高效博客创作:从明确项目标题到结构化关键词的完整指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/10 0:24:53

RRT与PRM串联运动规划算法在机器人导航中的应用

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/10 10:43:39

特种作业证到底什么工是特种作业?通过率揭秘帮你避开坑

特种作业证到底什么工是特种作业?通过率揭秘帮你避开坑 你缺的不是技术,是特种作业证!刚进工地就被要求拿证上岗,连面试机会都没给你,这年头什么工是特种作业?特种作业证怎么考?通过率又怎么样?这些问题,直接决定你能不能顺利上岗、拿到工资。今天咱…

2026/11/10 10:43:39

武汉特种作业操作证考试地点曝光内部消息 从业者必看避坑指南

武汉特种作业操作证考试地点曝光内部消息 从业者必看避坑指南 不知道去哪报名怕被中介坑?武汉特种作业操作证考试地点到底在哪?最近不少同行都在打听,特别是周口转岗过来的兄弟,对武汉的考试流程和报名方式不太熟悉,一不小心就踩坑。今天我就从…

2026/11/10 10:43:39

芙蓉区特种工建筑资质含金量高不高?外省证能转吗?

芙蓉区特种工建筑资质含金量高不高?外省证能转吗? 之前考的证在外省能不能转过来?这是很多在芙蓉区或者打算考芙蓉区特种工建筑资质的学员最关心的问题。特别是在建筑行业,特种作业证书是上岗的“硬门槛”,但如果你之前在外地考的证,现在想在芙蓉区从事…

2026/11/10 10:43:39

武汉特种作业操作证考试地点保姆级教程:新手避坑全攻略

武汉特种作业操作证考试地点保姆级教程:新手避坑全攻略 你是不是正在为 武汉特种作业操作证考试地点 发愁?或者担心自己在报名过程中被中介坑了?别急,今天这篇保姆级教程就是为像你一样的人量身打造的,从报名到考试、再到补办和复审,一步步带你走通流…

2026/11/10 10:43:39

电工证考什么试题怎么考才能不白交培训费?上岗必备干货全在这了

电工证考什么试题怎么考才能不白交培训费?上岗必备干货全在这了 怕考不过白交培训费?别急,电工证考什么试题,真题怎么练,我用十年行业经验告诉你,这不仅是上岗必备,更是你进工地、拿高薪的“通行证”。今天就从 考试内容、培训避坑、薪资前景…

2026/11/10 10:38:38

面试要求电工证合理吗?考前押题怎么用才有效

面试要求电工证合理吗?考前押题怎么用才有效 你有没有过这样的经历:面试时被问“你有电工证吗?”心里一咯噔,想着要是早几年考个证就好了。现在特种作业证已经成了不少岗位的门槛, 急需特种作业证才能上岗找工作…

2026/11/10 8:12:38

电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。…

2026/11/10 0:01:28

学历不高怕报不上名?考电工证报名费+网上查询全攻略来了

学历不高怕报不上名?考电工证报名费+网上查询全攻略来了 你是不是也担心自己学历不高,考电工证报名费太贵,根本报不上名?别急,今天就来给你讲讲,怎么用最少的钱,把证拿到手,还能在工地上多挣点钱。 电工证报名费多少钱?网上查询是关键…

2026/11/10 0:01:29

绍兴考电工证培训机构怎么选?2026河南最新政策别错过

绍兴考电工证培训机构怎么选?2026河南最新政策别错过 怕考不过白交培训费?你不是一个人。2026河南最新政策出台,对电工证考试、报名、培训、复审都有明确规定。选择绍兴考电工证培训机构,别再踩坑,下面一步步教你避坑。…

2026/11/9 6:30:27

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/10 10:29:37

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑