这是我过去用BenchmarkDotNet
测试的程序。我正在比较out
与元组的表现。
public class OutVsTuple
{
[Benchmark]
public void Out()
{
void OutLocal(out int a, out int b)
{
a = 1;
b = 2;
}
OutLocal(out int x, out int y);
int z = x + y;
}
[Benchmark]
public void Tuple()
{
(int a, int b) TupleLocal() => (1,2);
(int x, int y) = TupleLocal();
int z = x + y;
}
}
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<OutVsTuple>();
}
}
结果:
Method | Mean | Error | StdDev | Median |
------- |----------:|----------:|----------:|----------:|
Out | 0.0000 ns | 0.0000 ns | 0.0000 ns | 0.0000 ns |
Tuple | 5.3041 ns | 0.1422 ns | 0.3209 ns | 5.1754 ns |
我认为Out
的时间是0.0000,因为整个函数的结果可以知道,这使得该方法毫无意义。我改变它就像这样使用Random
。
public class OutVsTuple
{
System.Random r = new System.Random();
[Benchmark]
public void Out()
{
void OutLocal(out int a, out int b)
{
a = r.Next(0,100);
b = r.Next(0,100);
}
OutLocal(out int x, out int y);
int z = x + y;
}
[Benchmark]
public void Tuple()
{
(int a, int b) TupleLocal() => (r.Next(0,100),r.Next(0,100));
(int x, int y) = TupleLocal();
int z = x + y;
}
}
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<OutVsTuple>();
}
}
结果:
Method | Mean | Error | StdDev |
------- |---------:|----------:|----------:|
Out | 27.10 ns | 0.5799 ns | 1.2233 ns |
Tuple | 28.52 ns | 0.5486 ns | 0.4863 ns |
现在结果看起来更合理。
out
情况?聚苯乙烯。经过多次运行后,第一个案例最终返回非零,但仍然非常低。
Method | Mean | Error | StdDev |
------- |----------:|----------:|----------:|
Out | 0.0022 ns | 0.0080 ns | 0.0075 ns |
Tuple | 5.0376 ns | 0.1484 ns | 0.1823 ns |
答案 0 :(得分:1)
为什么元组函数需要时间才能很容易地知道结果?
这就是你的错误:元组版本实际上正在创建ValueTuple
结构的新实例。
带有out
参数的第一个版本相当于对常量的两个简单赋值。
元组版本实际上在概念上等同于:
var newTuple = new ValueTuple(1, 2);
var a = newTuple.Item1;
var b = newTuple.Item2;
并且需要更多时间,因为新的实例已经在运行时创建了,因此无法进行优化。
如果您尝试在DataRow
中使用元组,则可以看到元组不是常量:
[DataTestMethod]
[DataRow( (1, 2) )] // won't compile
void SomeTest( (double, double) args ) { }
编译器会抱怨你需要一个常量表达式,而元组则不是。