新闻详情

新闻详情

首页 / 资讯中心 / 详情

BenchmarkDotNet 数组参数基准测试实战:用 [ArgumentsSource] 将数组作为基准参数(IntroArrayParam 深度解析)

发布时间:2026/11/6 18:19:20来源:尧图网络
BenchmarkDotNet 数组参数基准测试实战:用 [ArgumentsSource] 将数组作为基准参数(IntroArrayParam 深度解析)
性能测试开发工具【免费下载链接】BenchmarkDotNetPowerful .NET library for benchmarking项目地址https://gitcode.com/gh_mirrors/be/BenchmarkDotNet点击查看免费下载BenchmarkDotNet 支持把数组、集合等复杂类型直接作为基准方法的参数本文以官方示例 IntroArrayParam 为骨架系统讲解[ArgumentsSource]的用法、数组参数的生命周期以及参数创建成本不计入基准这一关键语义。读完本文你将掌握如何为基准方法注入数组类型参数、如何设计多组参数化用例并从源码层面理解 BenchmarkDotNet 内部是如何解析与校验这些参数的。示例背景为什么需要数组参数常规的[Arguments]特性适合传少量标量值如int、string。但当你需要把一段真实数据——例如一个整数数组——作为基准输入时直接在特性里写数组字面量既不灵活也不可读。官方示例 IntroArrayParam 演示的正是这种场景两个基准方法都接收int[]数组和int值用[ArgumentsSource]统一提供多组数组 查找目标值的组合。该示例的核心价值在于对比两种数组查找实现的性能Array.IndexOf(array, value).NET 运行时内置的数组线性查找 API手写的for循环线性查找。通过把数组长度3与100和目标值命中第 4 个元素以及不存在的101作为参数展开可以一次跑出多种组合下的性能差异这正是 BenchmarkDotNet 参数化的典型用法。完整示例源码以下即官方示例的完整实现仓库路径samples/BenchmarkDotNet.Samples/IntroArrayParam.csusing BenchmarkDotNet.Attributes; namespace BenchmarkDotNet.Samples { public class IntroArrayParam { [Benchmark] [ArgumentsSource(nameof(Data))] public int ArrayIndexOf(int[] array, int value) Array.IndexOf(array, value); [Benchmark] [ArgumentsSource(nameof(Data))] public int ManualIndexOf(int[] array, int value) { for (int i 0; i array.Length; i) if (array[i] value) return i; return -1; } public IEnumerableobject[] Data() { yield return new object[] { new int[] { 1, 2, 3 }, 4 }; yield return new object[] { Enumerable.Range(0, 100).ToArray(), 4 }; yield return new object[] { Enumerable.Range(0, 100).ToArray(), 101 }; } } }要点拆解两个基准方法均带有[ArgumentsSource(nameof(Data))]参数提供者为同类的公共方法Data()Data()返回IEnumerableobject[]每个object[]元素对应一组参数按声明顺序映射到基准方法的形参(int[] array, int value)三组用例分别是长度 3 的数组查找存在的值4、长度 100 的数组查找存在的值4、长度 100 的数组查找不存在的值101。关于返回类型IEnumerableobject[]是历史兼容写法目前仍受支持但官方文档见 IntroArgumentsSource 说明已不再推荐改用带类型的元素形式如IEnumerable(int[] array, int value)或IEnumerableobject[]之外的强类型集合更佳配套的 Code Fix 也提供了自动转换支持。若数据源仅声明为非泛型IEnumerableBenchmarkDotNet 会直接拒绝因为生成代码无法从中推断参数类型。关键语义参数创建成本不计入基准原文档在示例开头特别用[!WARNING]强调了一个容易踩坑的事实创建参数arguments的开销不会计入基准结果。也就是说当你传入数组参数时BenchmarkDotNet 会在运行基准之前分配好这些数组基准循环中只测量方法体本身的执行时间数组的分配、填充等准备工作被完全排除在计时之外。这一语义从源码结构上可以得到印证在 BenchmarkConverter.cs 的GetParameterInstances流程中参数实例ParameterInstances是在生成基准用例阶段一次性构建的——[ArgumentsSource]指向的源方法通过GetValidValuesForParamsSourceAsync被读取并物化为值列表随后逐组转换为ParameterInstances挂到每个BenchmarkCase上。也就是说数据源只在用例发现阶段被枚举一次之后每个工作负载迭代直接复用已固化的参数值因此分配数组的耗时不会进入每次迭代的测量窗口。对应的设计含义是基准测试的是对给定数据的处理逻辑而非数据本身的构造。这在对比不同算法在相同输入下的表现时非常合理但如果你要测的恰恰是创建数据结构 处理的完整链路那就需要把构造逻辑写进基准方法体内而不是放进ArgumentsSource。与 [Arguments] / [Params] 的分工数组参数属于 BenchmarkDotNet 参数化体系的一部分官方文档 Parameterization 专题 将其与其他参数化手段并列。从 BenchmarkConverter.cs 的处理逻辑可以清晰看到它们的分工[Arguments]直接在特性中给出若干组值GetParameterInstances会校验值的个数与基准方法形参个数严格一致否则抛出InvalidOperationException[ArgumentsSource]从方法/属性读取多组参数适合值多、值复杂如数组、对象的场景[Params]/[ParamsSource]作用于字段或属性对同一基准展开多组配置。若基准方法带形参但既没有[Arguments]也没有[ArgumentsSource]AssertMethodHasCorrectSignatureBenchmarkConverter.cs会直接判定为非法声明并抛出InvalidBenchmarkDeclarationException。数组参数在结果表中的呈现运行该示例dotnet run -c Release后结果表如下引自 IntroArrayParam.md 的 Output 部分| Method | array | value | Mean | Error | StdDev | Allocated | |-------------- |----------- |------ |----------:|----------:|----------:|----------:| | ArrayIndexOf | Array[100] | 4 | 15.558 ns | 0.0638 ns | 0.0597 ns | 0 B | | ManualIndexOf | Array[100] | 4 | 5.345 ns | 0.0668 ns | 0.0625 ns | 0 B | | ArrayIndexOf | Array[3] | 4 | 14.334 ns | 0.1758 ns | 0.1558 ns | 0 B | | ManualIndexOf | Array[3] | 4 | 2.758 ns | 0.0905 ns | 0.1208 ns | 0 B | | ArrayIndexOf | Array[100] | 101 | 78.359 ns | 1.8853 ns | 2.0955 ns | 0 B | | ManualIndexOf | Array[100] | 101 | 80.421 ns | 0.6391 ns | 0.5978 ns | 0 B |观察要点array列数组参数在结果表中以Array[N]的形式呈现其长度Array[3]、Array[100]便于快速识别不同规模的输入Allocated列全为0 B这正是数组在基准前已分配好的直接证据——测量区间内两个方法都没有额外分配内存数值差异ManualIndexOf在小数组、命中靠前元素时明显更快2.758 nsvs14.334 ns而在 100 元素数组上查找不存在的101时两者耗时接近78.359 nsvs80.421 ns因为此时两者都必须遍历完整数组。注意这些数字是特定硬件上的示例输出在不同机器上会有差异但相对趋势具有参考意义。数据源机制的源码级剖析特性定义[ArgumentsSource]定义在 src/BenchmarkDotNet.Annotations/Attributes/ArgumentsSourceAttribute.cs继承自PriorityAttribute用于控制参数展开顺序仅可作用于方法AttributeTargets.Method不可重复使用[AttributeUsage(AttributeTargets.Method, AllowMultiple false)] public class ArgumentsSourceAttribute : PriorityAttribute { public string Name { get; } public Type? Type { get; } public ArgumentsSourceAttribute(string name) { ... } public ArgumentsSourceAttribute(Type type, string name) { ... } }两个构造函数对应两种引用方式[ArgumentsSource(nameof(Data))]引用同类成员[ArgumentsSource(typeof(OtherClass), nameof(OtherClass.Data))]引用外部类型中的成员此时Type属性非空。参数解析与校验解析入口BenchmarkConverter.GetParameterInstancesBenchmarkConverter.cs在检测到[ArgumentsSource]后通过GetValidValuesForParamsSourceAsync读取源数据再用SmartParamBuilder.CreateForArguments逐组构建ParameterInstances。数据源只会被枚举一次枚举结果被固化到用例中。行内取值SmartParamBuilder.CreateForArgumentsSmartParamBuilder.cs中整组参数一行只做一次SourceRead即每个用例只读取一次源而不是为每个形参分别读取随后按声明类型把一行拆给各个参数。数量校验如果源方法产出的参数个数与基准方法形参个数不一致会抛出InvalidBenchmarkDeclarationException提示invalid number of arguments provided by [ArgumentsSource(...)]。返回类型校验SourceReturnTypeValidatorSourceReturnTypeValidator.cs在运行期对每个[ArgumentsSource]成员做可达性与可读性校验并注明它是BDN1306、BDN1308、BDN1311、BDN1504这些分析器规则的运行时对等物对应实现见 ArgumentsAttributeAnalyzer.cs用于约束源必须返回可枚举类型产出的元素必须与形参匹配等约束。数据源的形式要求结合 IntroArgumentsSource 文档 与 参数化专题[ArgumentsSource]指向的源需满足是公共方法或属性返回IEnumerableT或IAsyncEnumerableT元素类型必须是具名类型——仅返回非泛型IEnumerable会被拒绝元素到形参的映射由元素类型决定单参数基准元素即参数值本身如IEnumerableTimeSpan对应TimeSpan参数多参数基准每个元素是一组完整参数如IEnumerable(int[] array, int value)或本文示例的IEnumerableobject[]by-ref-like 参数如ReadOnlySpanbyte源产出的是其转换源类型如IEnumerablebyte[]源可以是实例方法也可以是静态方法若源不在基准类中需在特性构造器中用typeof显式指定返回IAsyncEnumerableT的源会被异步等待读取且源方法可带[EnumeratorCancellation] CancellationToken可选参数。扩展实践复杂类型与数组组合如果数组元素本身是自定义类型官方文档提供了更完整的实践模式见 IntroArgumentsSource.md 的 Another example对非基础类型参数重写ToString()即可定制结果表中该参数的显示名。示例中SomeClass重写ToString()返回${Values.Length} items最终结果表里该列显示为10 items、15 items而非默认的类型全名。同理当你以数组为参数时若数组元素是自定义对象也可通过自定义参数包装类型并重写ToString()来控制array列的显示文本让结果表更易读。小结通过[ArgumentsSource]向基准方法传入数组参数是把真实数据规模纳入基准设计的标准做法数据源在用例发现阶段一次性构建数组分配成本不计入测量结果表中以Array[N]展示输入规模。配合源码层的解析BenchmarkConverter、行内取值与数量校验SmartParamBuilder以及运行期校验SourceReturnTypeValidator你可以放心地把数组、集合乃至异步数据源投入参数化基准。更完整的参数化手段对照可继续阅读 Parameterization 专题 与同系列示例 IntroArguments、IntroArgumentsSource、IntroParamsSource。赞分享性能测试开发工具【免费下载链接】BenchmarkDotNetPowerful .NET library for benchmarking项目地址https://gitcode.com/gh_mirrors/be/BenchmarkDotNet点击查看免费下载相关推荐BenchmarkDotNet 参数化基准四用 [ArgumentsSource] 为基准方法批量提供参数BenchmarkDotNet 参数化基准四用 ArgumentsSource 为基准方法批量提供参数 导读 当基准方法的参数数量较多、无法或不宜通过性能测试开发工具BenchmarkDotNet 参数化基准[Params] 特性实现多参数组合测试的完整指南BenchmarkDotNet 参数化基准 Params 特性实现多参数组合测试的完整指南 导读 本指南以 BenchmarkDotNet 官方示例 Intr性能测试开发工具用 [ParamsAllValues] 自动穷举枚举与布尔参数的 BenchmarkDotNet 参数化基准测试用 ParamsAllValues 自动穷举枚举与布尔参数的 BenchmarkDotNet 参数化基准测试 导读 ParamsAllValues 是 Benc性能测试开发工具上一篇awesome-low-level-design微内核架构构建灵活可扩展的底层系统下一篇Waterius 水表数据永不丢失的秘密EEPROM 环形缓冲 CRC8 校验存储原理全解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

【外设】之大彩串口显示屏 2026/11/6 6:37:16

【外设】之大彩串口显示屏

大彩串口屏初步使用 1 .官网下载 STM32 屏幕 GUI 设计资料 http://www.gz-dc.com/category/typeid/4112 找到 STM32 Keil 工程,移植相关代码因项目而异进行移植,由于项目简单,本人只对用到的指令接口进行修改。 比如:注意事项&…

阅读更多 →
无法下载Windows系统iso文件 2026/11/6 0:32:51

无法下载Windows系统iso文件

当我遇到这个问题的时候,我打开了一个网站: 登录 然后我打算下载的时候: 突然那个官方的连接就可以下载了:

阅读更多 →
【清华代码熊】DeepSeek V4.1 Flash 后训练详解 2026/11/6 1:10:54

【清华代码熊】DeepSeek V4.1 Flash 后训练详解

📌 上期解析了 DeepSeek V4.1 Flash 模型架构改进,本期解析 DeepSeek V4.1 Flash 预训练/后训练技术: 🌟 预训练:45T 文本 多模态混合语料、直接训练 sparse attention(取消 DeepSeek V4 的 dense 冷启动&…

阅读更多 →
Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ... 2026/11/6 17:25:36

Shuffle-R1: Efficient RL framework for Multimodal Large Language Models via Data-centric Dynamic ...

文章主要内容和创新点 主要内容 本文聚焦于多模态大语言模型(MLLM)强化学习(RL)训练中的效率问题,提出了一个名为Shuffle-R1的框架。研究发现,当前RL训练存在两个关键缺陷: 优势值坍缩(Advantage Collapsing):批次中大多数优势值集中在零附近,导致有效梯度信号被淹…

阅读更多 →
PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction 2026/11/6 14:29:05

PRvL: Quantifying the Capabilities and Risks of Large Language Models for PII Redaction

一、文章主要内容总结 本文聚焦于利用大型语言模型(LLMs)实现个人身份信息(PII)脱敏的研究,旨在解决传统脱敏方法(如基于规则的系统、领域特定命名实体识别(NER)模型)泛化能力差、跨格式/跨语境适应性弱的问题。 研究通过全面评估多种LLM架构(包括密集型LLM(D-LLM…

阅读更多 →
LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model 2026/11/6 14:29:07

LLaVA-RE: Binary Image-Text Relevancy Evaluation with Multimodal Large Language Model

文章主要内容和创新点 主要内容 本文聚焦于二进制图像-文本相关性评估任务(判断图像与文本“相关”或“不相关”),针对该任务中文本格式多样、相关性定义随场景变化等挑战,提出了基于多模态大语言模型(MLLM)的解决方案LLaVA-RE。 模型设计:LLaVA-RE基于LLaVA 1.5架构,…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉