在编写单元测试时,我们可以通过简单地向集合添加元素来添加更多的测试用例,例如在NUnit中使用TestCaseSource
。
是否可以在BenchmarkDotNet中执行类似的操作,并从集合中创建一组基准?
这将节省大量的样板,尤其是在对多个输入组合进行基准测试或对基准测试方法进行额外测试时。
最小示例代码:
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
public interface IAlgorithm
{
public void DoWork();
}
public class AlgorithmA: IAlgorithm
{
public void DoWork() { } // something slow
}
public class AlgorithmB : IAlgorithm
{
public void DoWork() { } // something slow
}
public class MyBenchmarks
{
AlgorithmA classA = new AlgorithmA();
AlgorithmB classB = new AlgorithmB();
[Benchmark]
public void A() => classA.DoWork();
[Benchmark]
public void B() => classB.DoWork();
}
public class WhatIWouldLike
{
IAlgorithm[] classes = new IAlgorithm[] { new AlgorithmA(), new AlgorithmB() };
// ...automatically create a benchmark for DoWork() on element of the array
}
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<MyBenchmarks>();
}
}
有参数化的基准测试。在这种情况下,您可以使用ArgumentsSource
或ParamsSource
。
ArgumentsSource
的示例,在使用方式方面与TestCaseSource
类似:
public class Algorithm1: IAlgorithm {
public void DoWork() {
...
}
// override ToString so that we have a more readable table of results
public override string ToString() => "Algorithm 1";
}
public class Algorithm2: IAlgorithm {
public void DoWork() {
...
}
public override string ToString() => "Algorithm 2";
}
public class MyBenchmarks {
public IEnumerable<IAlgorithm> Algorithms() {
yield return new Algorithm1();
yield return new Algorithm2();
// add more algorithms here if needed
}
[Benchmark]
[ArgumentsSource(nameof(Algorithms))]
public void RunAlgorithm(IAlgorithm algorithm) => algorithm.DoWork();
}
你可以得到这样的表格:
| Method | algorithm | Mean | Error | StdDev |
|------------- |------------ |---------:|----------:|----------:|
| RunAlgorithm | Algorithm 1 | 1.146 ms | 0.0065 ms | 0.0061 ms |
| RunAlgorithm | Algorithm 2 | 2.223 ms | 0.0120 ms | 0.0106 ms |