【发布时间】:2017-07-12 16:47:51
【问题描述】:
有时我想为原始双精度添加更多类型安全。经常出现的一个想法是在类型中添加单元信息。例如,
struct AngleRadians {
public readonly double Value;
/* Constructor, casting operator to AngleDegrees, etc omitted for brevity... */
}
在像上面这样只有一个字段的情况下,JIT 是否能够在所有情况下优化掉这个抽象?与使用未包装双精度的类似代码相比,哪些情况(如果有)会导致生成额外的机器指令?
任何提及过早优化的内容都将被否决。我有兴趣了解基本事实。
编辑: 为了缩小问题的范围,这里有几个特别感兴趣的场景......
// 1. Is the value-copy constructor zero cost?
// Is...
var angleRadians = new AngleRadians(myDouble);
// The same as...
var myDouble2 = myDouble;
// 2. Is field access zero cost?
// Is...
var myDouble2 = angleRadians.Value;
// The same as...
var myDouble2 = myDouble;
// 3. Is function passing zero cost?
// Is calling...
static void DoNaught(AngleRadians angle){}
// The same as...
static void DoNaught(double angle){}
// (disregarding inlining reducing this to a noop
这些是我能想到的一些事情。当然,像@EricLippert 这样优秀的语言设计师可能会想到更多的场景。所以,即使这些典型的用例是零成本的,我仍然认为最好知道 JIT 是否不将一个结构保持一个值和未包装的值视为等效的任何情况,而不列出每个可能的代码 sn-p 作为它自己的问题
【问题讨论】:
-
你为什么不尝试做一些测试?
-
如果你想知道两匹马哪一匹更快,你是在网上问陌生人,还是赛马?您想知道提议的计划的成本,然后运行该计划,很快您就会知道它的成本!
-
抛开性能问题不谈,我建议使用
AngleDegrees、AngleRadians、AngleGradians等类型是个坏主意。有一个Angle类型,它具有AsDegrees、AsRadians等属性和工厂FromRadians等属性。您的类型的实现细节就是:实现细节。通过将实现细节嵌入到类型的名称中,您限制了您的创新能力并降低了抽象级别。 -
我觉得这个问题太笼统了。您基本上是在说“想想我可以用这种类型做的所有可能的事情,并向我展示 JIT 编译器以我想要的方式对其进行优化”。对于一个问题,这要求太多了。
-
@EricLippert 实际上,一个具有 AsDegrees/AsRadians 属性和工厂方法 FromRadians 的 Angle 结构正是我现在拥有的代码。为简单起见,我选择了 Angle,但有时在空间之间进行转换并不便宜,因此要求 API 用户明确而不是在幕后进行工作很有用。可怕的例子 - Vector3Cartesian 和 Vector3Polar
标签: c# performance cil ryujit