【发布时间】:2010-10-12 13:57:26
【问题描述】:
我在 XNA 中四处寻找,发现其中的 Vector3 类使用公共字段而不是属性。我尝试了一个快速基准测试,发现对于struct,差异非常显着(将两个向量加在一起 1 亿次需要 2.0 秒的属性和 1.4 秒的字段)。对于引用类型,差异似乎并没有那么大,但确实存在。
那是为什么呢?我知道一个属性被编译成get_X 和set_X 方法,这会产生方法调用开销。但是,这些简单的 getter/setter 总是 不会被 JIT 内联吗?我知道你不能保证 JIT 决定做什么,但肯定这在概率列表中相当高吗?还有什么可以将公共字段与机器级别的属性分开?
我一直想知道的一件事是:自动实现的属性 (public int Foo { get; set; }) 如何比公共字段“更好”的 OO 设计?或者更好地说:这两个不同有什么不同?我知道通过反射使它成为一个属性更容易,但还有什么?我敢打赌这两个问题的答案是一样的。
顺便说一句:我正在使用 .NET 3.5 SP1,我相信它解决了带有结构的方法(或方法 of 结构,我不确定)没有内联的问题,所以这是不是。我想我至少在使用它,它肯定已经安装了,但话又说回来,我使用的是带有 SP1 的 Vista 64 位,它应该有 DX10.1,但我没有 DX10.1 ..
另外:是的,我一直在运行发布版本 :)
编辑:感谢大家的快速回答,但我表示我确实知道属性访问是一种方法调用,但我不知道为什么大概,内联方法比直接字段访问慢。
编辑 2:所以我创建了另一个 struct,它使用了明确的 GetX() 方法(我怎么不会错过我的 Java 日子)无论我是否禁用内联(通过[MethodImplAttribute(MethodImplOptions.NoInlining)])都执行相同的操作,所以结论是:非静态方法显然永远不会内联,甚至在结构上也不会。
我认为存在例外情况,JIT 可以优化虚拟方法调用。为什么这种情况不会发生在不知道继承的结构上,因此方法调用只能指向一个可能的方法,对吧?还是因为你可以在上面实现一个接口?
这有点可惜,因为它真的会让我考虑在性能关键的东西上使用属性,但是使用字段让我觉得很脏,我还不如用 C 来写我正在做的事情。
编辑 3:我发现 this 发布了完全相同的主题。他的最终结论是属性调用确实得到了优化。我也可以发誓,我已经读过很多次简单的 getter/setter 属性将被内联,尽管在 IL 中是 callvirt。那我是不是要疯了?
编辑 4:Reed Copsey 在下面的评论中发布了答案:
回复:Edit3 - 查看我更新的评论:我相信这是 x86 JIT 与 x64 JIT 的问题。 x64 中的 JIT 并不成熟。随着越来越多的 64 位系统每天上线,我希望 MS 能够迅速改进这一点。 ——里德·科普西
我对他的回答的回应:
谢谢,这就是答案!我尝试强制 x86 构建,所有方法都同样快,而且比 x64 快得多。实际上,这对我来说非常令人震惊,我不知道我生活在我的 64 位操作系统上的石器时代。我会在我的回答中包含您的评论,这样它会更好。 – 朱利安R
谢谢大家!
【问题讨论】:
-
问题:如果该字段是公共的但也有一个属性会发生什么。那么它是内联的吗?
-
回复:Edit3 - 查看我更新的评论:我相信这是 x86 JIT 与 x64 JIT 的问题。 x64 中的 JIT 并不成熟。随着每天都有更多的 64 位系统上线,我希望 MS 能够迅速改进这一点。
-
谢谢,这就是答案!我尝试强制 x86 构建,所有方法都同样快,而且比 x64 快得多。实际上,这对我来说非常令人震惊,我不知道我在 64 位操作系统上生活在石器时代。我会将您的评论包含在我的答案中,以便更好地脱颖而出。
-
我在下面有一个答案 - 还为您提供了有关其他相关主题的更多信息 :)
-
顺便说一句 - 这启发了我问:stackoverflow.com/questions/635019/…
标签: c# oop properties struct public-fields