gpt4 book ai didi

C# 编译器可以折叠返回常量的函数吗?

转载 作者:行者123 更新时间:2023-11-30 17:30:25 24 4
gpt4 key购买 nike

这是我用 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 |

现在结果看起来更合理了。

  1. 编译器是否像我猜测的那样有任何机制来折叠函数?
  2. 为什么像 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com