Ily*_*lya 11 c# performance struct operator-keyword
我试图通过将double包装到struct中来获得我称之为测量单位系统的东西.我有C#结构,如Meter,Second,Degree等.我最初的想法是,在编译器内联所有内容后,我将获得与使用double时相同的性能.
我的显式和隐式运算符简单明了,编译器实际上内联它们,但是Meter和Second的代码比使用double的相同代码慢10倍.
我的问题是:为什么C#编译器不能使用Second作为使用double的代码的最佳代码,如果它无论如何都要内联?
第二个定义如下:
struct Second
{
double _value; // no more fields.
public static Second operator + (Second left, Second right)
{
return left._value + right._value;
}
public static implicit Second operator (double value)
{
// This seems to be faster than having constructor :)
return new Second { _value = value };
}
// plenty of similar operators
}
Run Code Online (Sandbox Code Playgroud)
更新:
我没有问结构是否适合这里.确实如此.
我没有询问代码是否会被内联.JIT确实内联它.
我检查了运行时发出的汇编操作.对于像这样的代码,它们是不同的:
var x = new double();
for (var i = 0; i < 1000000; i++)
{
x = x + 2;
// Many other simple operator calls here
}
Run Code Online (Sandbox Code Playgroud)
和这样:
var x = new Second();
for (var i = 0; i < 1000000; i++)
{
x = x + 2;
// Many other simple operator calls here
}
Run Code Online (Sandbox Code Playgroud)
在反汇编中没有调用指令,因此操作实际上是内联的.然而,差异很大.性能测试表明,使用Second比使用double慢10倍.
所以我的问题是(注意!):为什么JIT生成的IA64代码对于上述情况有所不同?如何使struct运行速度与double一样快?似乎双重和第二之间没有理论上的差异,我看到差异的深层原因是什么?
C# 编译器不会内联任何内容- JIT可能会这样做,但没有义务这样做。但它应该仍然足够快。我可能会删除其中的隐式转换+(请参阅下面的构造函数用法) - 还要查看另一个运算符:
private readonly double _value;
public double Value { get { return _value; } }
public Second(double value) { this._value = value; }
public static Second operator +(Second left, Second right) {
return new Second(left._value + right._value);
}
public static implicit operator Second(double value) {
return new Second(value);
}
Run Code Online (Sandbox Code Playgroud)
JIT内联仅限于特定场景。这段代码会让他们满意吗?很难说 - 但对于大多数情况来说它应该可以工作并且工作得足够快。问题+是有一个用于添加双精度数的 IL 操作码;它几乎没有任何作用 - 当你的代码调用一些静态方法和构造函数时;即使是内联的,总会有一些开销。