这是我用 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 |
最佳答案
Why the tuple function takes time when the result can be easily known like the out case?
这是您的错误:元组版本实际上是在创建 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 ) { }
编译器会提示你需要常量表达式,而元组不需要。
关于C# 编译器可以折叠返回常量的函数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49897252/