属性比字段慢
Properties slower than fields
似乎我遇到的每个 post 都达成了相同的共识:仅 return 字段的属性由 JIT 内联并且具有与字段几乎相同的性能。
但是,我目前的情况似乎并非如此。我的程序进行密集计算,访问许多简单的自动获取器和私有设置器的属性。然而,在这种特殊情况下,我只是复制一个对象。
在启用优化的发布模式下分析代码会导致多次调用 属性 的 get
函数。对 Copy()
的调用总计约 5.6 毫秒。
但是,当属性被转换为字段时,该函数的运行速度比使用属性快 6 倍:
与使用字段相比,比较两个属性的相等性似乎会导致更多的性能损失。这是 class 的 IEquatable
实现的基准测试,使用相同的代码但将属性与字段交换。
如果 JIT 应该通过内联来优化属性,为什么会发生这种情况?我想保留属性,因为它们的访问控制方面非常方便,但如果它们慢得多,我会坚持使用字段。
编辑: 似乎受此问题影响的一些(但不是全部)案例正在使用接口中声明的属性。在这些情况下没有使用其他多态性,但在这些情况下删除接口会使性能差异达到预期水平。
编辑 2: 如上次编辑所述,部分问题似乎是由于接口虚拟调用引起的。经过更多调查,似乎 运行 CLR 中的基准测试正确地内联属性,但 JetBrains dotTrace 没有,即使选中 "Enable inline"。
不幸的是,除了尝试使用
来帮助消除 JITTER 之外,您无能为力
[MethodImpl(MethodImplOptions.AggressiveInlining)]
AggressiveInlining The method should be inlined if possible.
从技术上讲,这只能用在方法或构造函数上,但是您似乎可以在 getter 和 setter 本身上对其进行测试。即它可以编译(虽然我还没有测试过)
public int someType
{
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
get;
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
set;
}
注意 : 内联是一个神奇的黑盒,抖动可能喜欢也可能不喜欢,甚至属性也只是一个建议。另请注意,位数也可能会影响它内联的内容。
最后,我认为你的做法是正确的,你应该只使用 bechmarker 或分析器,并相应地进行微优化,
似乎我遇到的每个 post 都达成了相同的共识:仅 return 字段的属性由 JIT 内联并且具有与字段几乎相同的性能。
但是,我目前的情况似乎并非如此。我的程序进行密集计算,访问许多简单的自动获取器和私有设置器的属性。然而,在这种特殊情况下,我只是复制一个对象。
在启用优化的发布模式下分析代码会导致多次调用 属性 的 get
函数。对 Copy()
的调用总计约 5.6 毫秒。
但是,当属性被转换为字段时,该函数的运行速度比使用属性快 6 倍:
与使用字段相比,比较两个属性的相等性似乎会导致更多的性能损失。这是 class 的 IEquatable
实现的基准测试,使用相同的代码但将属性与字段交换。
如果 JIT 应该通过内联来优化属性,为什么会发生这种情况?我想保留属性,因为它们的访问控制方面非常方便,但如果它们慢得多,我会坚持使用字段。
编辑: 似乎受此问题影响的一些(但不是全部)案例正在使用接口中声明的属性。在这些情况下没有使用其他多态性,但在这些情况下删除接口会使性能差异达到预期水平。
编辑 2: 如上次编辑所述,部分问题似乎是由于接口虚拟调用引起的。经过更多调查,似乎 运行 CLR 中的基准测试正确地内联属性,但 JetBrains dotTrace 没有,即使选中 "Enable inline"。
不幸的是,除了尝试使用
来帮助消除 JITTER 之外,您无能为力[MethodImpl(MethodImplOptions.AggressiveInlining)]
AggressiveInlining The method should be inlined if possible.
从技术上讲,这只能用在方法或构造函数上,但是您似乎可以在 getter 和 setter 本身上对其进行测试。即它可以编译(虽然我还没有测试过)
public int someType
{
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
get;
[MethodImplAttribute(MethodImplOptions.AggressiveInlining)]
set;
}
注意 : 内联是一个神奇的黑盒,抖动可能喜欢也可能不喜欢,甚至属性也只是一个建议。另请注意,位数也可能会影响它内联的内容。
最后,我认为你的做法是正确的,你应该只使用 bechmarker 或分析器,并相应地进行微优化,