我正试图测试在 C# 中添加的 "in" 关键字的性能表现(或不行)。"in" 关键字应该能够将只读引用传递给值类型,而不是先复制值再传递。
通过绕过这个复制,"in" 应该更快,但在我的测试中似乎根本没有更快。
我正在使用 BenchMarkDotNet 来对我的代码进行基准测试。代码看起来像:
public struct Input
{
public decimal Number1 { get; set; }
public decimal Number2 { get; set; }
}
public class InBenchmarking
{
const int loops = 50000000;
Input inputInstance;
public InBenchmarking()
{
inputInstance = new Input
{
};
}
[Benchmark]
public decimal DoSomethingRefLoop()
{
decimal result = 0M;
for (int i = 0; i < loops; i++)
{
result = DoSomethingRef(ref inputInstance);
}
return result;
}
[Benchmark]
public decimal DoSomethingInLoop()
{
decimal result = 0M;
for (int i = 0; i < loops; i++)
{
result = DoSomethingIn(inputInstance);
}
return result;
}
[Benchmark(Baseline = true)]
public decimal DoSomethingLoop()
{
decimal result = 0M;
for (int i = 0; i < loops; i++)
{
result = DoSomething(inputInstance);
}
return result;
}
public decimal DoSomething(Input input)
{
return input.Number1;
}
public decimal DoSomethingIn(in Input input)
{
return input.Number1;
}
public decimal DoSomethingRef(ref Input input)
{
return input.Number1;
}
}
如您所见,我包含了一个循环来使用"ref"关键字,它也是通过引用传递的,但不是只读的。这似乎更快。
此测试的结果为:
Method | Mean | Error | StdDev | Scaled | ScaledSD |
------------------- |---------:|----------:|----------:|-------:|---------:|
DoSomethingRefLoop | 20.15 ms | 0.3967 ms | 0.6058 ms | 0.41 | 0.03 |
DoSomethingInLoop | 48.88 ms | 0.9756 ms | 2.5529 ms | 0.98 | 0.08 |
DoSomethingLoop | 49.84 ms | 1.0872 ms | 3.1367 ms | 1.00 | 0.00 |
使用"in"似乎并没有更快。我感觉可能有一些优化是以一种我没有预料到的方式进行的,这解释了性能差异。我已经尝试将结构体的大小增加到16个十进制字段,但在传递方式为"in"和按值传递之间并没有区别。
我该如何构建基准测试以真正看到"in"、"ref"和按值传递之间的差异?