Sas*_*ssa 6 c# optimization jit compiler-optimization
我通常使用具有零成本抽象概念的语言进行编程,例如 C++ 和 Rust。
目前我正在从事一个使用C#语言的项目。所以我想知道是否可以安全地创建抽象和更高级别的代码而不影响性能。
这在 C# 中可能吗?或者对于性能关键的代码,我应该只执行尽可能低级的代码?
正如我在代码中遇到的一个例子(不要过多关注这个例子,我的问题更高级别),我需要一个返回多个值的函数,为此,我的第一个方法是使用元组,所以像这样:
public (int, int, float) Function();
Run Code Online (Sandbox Code Playgroud)
或将此元组抽象为结构:
public struct Abstraction { int value1; int value2; float value3; };
public Abstraction Function();
Run Code Online (Sandbox Code Playgroud)
我期望编译器会优化Tuple或Abstraction struct直接直接使用原始值。但我发现使用参数编写代码out可以提高性能:
public void Function(out int value1, out int value2, out float value3);
Run Code Online (Sandbox Code Playgroud)
我猜原因是因为在out函数中没有Tuple或Abstraction struct创建。
函数版本的问题out是我真的很讨厌使用参数作为返回值,因为它看起来更像是对语言限制的破解。
所以,最后我不确定我是否只是没有使用正确的配置,以便 JIT 可以使用零成本抽象,或者这在 C# 中根本不可能或无法保证。
当您返回某些内容时,您总是创建一个新对象 \xe2\x80\x93 ,当您仅使用参数“就地”工作时,您可以完全保存该步骤out。
然后,你的编译器无法简单地优化掉 \xe2\x80\x93 我必须告诉你一些有关 C 中严格别名规则的内容,但我对 C# 的了解还不足以知道是否类似的事情也适用于此。
\n\n因此,一般来说,创建元组或Abstraction类型的对象是不可优化的。您明确指定要返回该类型的对象,因此该对象必须通过该函数的“常规”编译来创建。您可能会争辩说,编译器知道调用的上下文,Function并且可以推断不生成对象而是直接工作,就好像这些是对Abstraction稍后分配字段的事物的引用一样,但这里是别名规则可能会变得非常复杂,而这通常在逻辑上是不可能做到的。