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

发布时间:2026/9/14 9:03:50

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/9/14 9:03:50

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

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

2026/9/14 9:03:50

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

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

2026/9/14 8:58:50

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/9/14 9:49:19

Vue组件开发:直接操作DOM与数据驱动的对比与实践

1. Vue组件开发的两种范式之争 在Vue项目开发中,组件化开发已经成为标配。但很多开发者经常面临一个基础却关键的选择题:到底该用直接操作DOM的传统写法,还是采用数据驱动的响应式写法?这个问题看似简单,却直接影响着项…

2026/9/14 9:49:18

Python SMTP加密端口邮件发送实战指南

1. Python实现加密端口发送邮件的核心原理在现代互联网通信中,邮件传输的安全性至关重要。Python通过内置的smtplib库提供了完整的SMTP协议实现,支持多种加密方式确保邮件传输安全。SMTP(Simple Mail Transfer Protocol)是用于发送…

2026/9/14 9:49:18

大模型转型实战:LangChain与RAG技术解析

1. 2026年大模型转型全景图:为什么现在就要开始准备? 大模型技术正在以惊人的速度重塑整个IT行业。根据行业观察,到2026年,超过70%的企业级应用都将集成大模型能力。作为技术人员,我们正站在一个关键的转型节点上——要…

2026/9/14 9:44:18

5 分钟跑通 Keep:AIOps 告警聚合与降噪怎么做到的

5 分钟跑通 Keep:AIOps 告警聚合与降噪怎么做到的 【免费下载链接】keep The open-source AIOps and alert management platform 项目地址: https://gitcode.com/GitHub_Trending/kee/keep 凌晨三点,Prometheus、Datadog、CloudWatch 同时炸出两三…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

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

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

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