Using C# types to express units of measure
我试图通过将double包装成struct来获得我所称的度量单位系统。我有C结构,如米、秒、度等。我最初的想法是,在编译器内联之后,我将拥有与使用double相同的性能。
我的显式和隐式操作符简单而直接,编译器实际上是将它们内联的,但是使用meter和second的代码比使用double的相同代码慢10倍。
我的问题是:为什么C编译器不能使使用第二个的代码像使用Double的代码一样最佳,如果它无论如何都能输入所有的代码?
第二个定义如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 } |
更新:
我没有问结构是否适合这里。是的。
我没有问代码是否要内联。JIT会内联它。
我检查了运行时发出的程序集操作。对于这样的代码,它们是不同的:
1 2 3 4 5 6 | var x = new double(); for (var i = 0; i < 1000000; i++) { x = x + 2; // Many other simple operator calls here } |
号
就像这样:
1 2 3 4 5 6 | 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一样快?似乎在理论上,二次和二次之间没有区别,我看到的区别的深层原因是什么?
这是我的观点,如果你不同意,请写一个评论,而不是沉默的投反对票。
C编译器不会内联它。JIT编译器可能会,但这对我们来说是不确定的,因为Jiter的行为并不简单。
在
为了优化它,首先用
C编译器不内联任何东西——JIT可能会这样做,但没有义务这样做。不过,它还是应该足够快的。我可能会删除
1 2 3 4 5 6 7 8 9 | 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); } |
JIT内联仅限于特定场景。这个代码能满足他们吗?很难说,但在大多数情况下,它应该工作得足够快。