说我有一个结构:
struct MyStruct
{
public int X
public int Y
}
某个类中的方法在其他地方多次迭代:
public bool MyMethod( MyStruct myStruct )
{
return ...
}
将MyMethod签名更改为以下可接受的优化吗?
public bool MyMethod( ref MyStruct myStruct )
如果是这样,它真正有多大的优势?如果没有,那么使用ref
这种方式,结构需要多少字段以获得足够大的优势?
答案 0 :(得分:7)
在32位系统上,您将进行更改以推送8个字节的数据而不是4个字节。在64位系统上推送的数据量没有变化。您还要向编译器/ JITter添加一个要求结构必须存在于内存中的要求,因为您将获取它的地址,这可能会否定其他优化。
我怀疑这会显示您的计划中的任何性能提升。首先介绍一下,看看MyMethod是否是你程序中的瓶颈。
然后,假设MyMethod中没有其他优化机会,请将更改传递给ref,然后再次进行配置以查看是否有任何改进。
答案 1 :(得分:4)
既然你明确询问它是否“可以接受”......
我会回答没有。通过ref
传递参数,你对编译器和程序员撒谎; .NET中的ref
(独占)意味着您打算修改方法内的参数。
当然,你可以提供一个额外的评论来解释程序员的“谎言”(但不是编译器......)。但为什么首先滥用语义?
如果你真的需要这种极端的微优化(并且看到其他答案 - 任何性能优势都有可能因为多种原因而受到质疑!).NET可能只是错误的环境。在C ++中实现相关部分。
答案 2 :(得分:2)
根据你的例子,不太可能。在64位处理器上,该结构可以很好地适应寄存器,不会通过堆栈传递。虽然不是32位处理器和实例方法。当您通过引用传递时,您需要为访问结构成员付费,需要额外的指针取消引用。这可能会比避免副本更加昂贵,ymmv。
支付通常在结构超过16个字节时开始。当结构变大时,共同指导切换到类的一个原因。鉴于这完全取决于使用情况,您要么必须分析代码并阅读程序集(当然是发布版本)或使用分析器。分析器不太可能显示出差异。通常很难测量纳秒,除非你人为地做了十亿次。
答案 3 :(得分:0)
有两个int
字段,优势将非常小,不太可能产生影响。它可能没有任何区别。
一旦开始添加两个以上的Int字段,这个优势就会开始上升。但是,除非你正在调用很多的方法,否则不够重要。
答案 4 :(得分:0)
在 general 中我会说不:坚持使用属性的类。但是,有些情况可能会调用类似的东西 - 特别是在紧凑框架(思考:XNA)或微框架上。在这两种情况下,GC 非常不同,对象分配(和非确定性集合)可能会对应用程序产生重大影响。
在这种情况下,看到更多的结构发挥作用并不是闻所未闻的,ref
避免了常见的“丢失更新”问题(在大多数 .NET中,结构应该是不可变的;再一次,XNA 确实有一些场景让它很有可能违反这个规则)。另一种方法当然是接受并返回数据 - 然后类型可以是不可变的。
如果你的意思是传递物体的表现;那么你有来描述你想要使用的确切设置。 x86 vs x64是明显的区别,但还有更多。例如,使用ref
要求值在字段或局部变量中 - 但结构上的许多JIT性能调整都在堆栈的头部工作 - 这意味着你可能有更多的“ldloc” /“stloc”比你严格需要的。你还引入了一个额外的解引用。