【发布时间】:2011-05-07 21:53:23
【问题描述】:
我试图通过将 double 包装到结构中来获得我所谓的测量单位系统。我有 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
}
更新:
我没有问 struct 是否适合这里。确实如此。
我没有问代码是否会被内联。 JIT 确实内联它。
我检查了运行时发出的汇编操作。对于这样的代码,它们是不同的:
var x = new double();
for (var i = 0; i < 1000000; i++)
{
x = x + 2;
// Many other simple operator calls here
}
像这样:
var x = new Second();
for (var i = 0; i < 1000000; i++)
{
x = x + 2;
// Many other simple operator calls here
}
反汇编中没有调用指令,因此操作实际上是内联的。然而,差异是显着的。性能测试表明,使用 Second 比使用 double 慢 10 倍。
所以我的问题是(注意!):为什么 JIT 生成的 IA64 代码与上述情况不同?有什么办法可以让 struct 运行得快一倍? double 和 Second 之间似乎没有理论上的区别,我看到的区别的深层原因是什么?
【问题讨论】:
-
这是
implicit或+运算符吗? -
我知道您使用的是 C#,但您考虑过 F# 吗?它内置了静态单元检查您似乎正在寻找的东西。见stackoverflow.com/questions/40845/…
-
与此非常相似:stackoverflow.com/questions/3995920/… 根据我的经验,编译器在优化结构方面相对较好。但是您需要编译为
release并且没有附加调试器。 -
我很久以前做过这样的事情来将“宽度”与“高度”分开,因为我们有很多方法可以将它们按不同的顺序排列。 int 和类型之间存在隐式转换,但它们之间没有。它适用于给定的项目。
标签: c# performance struct operator-keyword