简体   繁体   English

C#中双重解引用引用类型的性能下降

[英]Performance hit of double dereferencing Reference types in C#

Recently, I started working on a project where many reference parameters are passed around by reference. 最近,我开始从事一个通过引用传递许多参考参数的项目。 I've looked into a lot of the code and the majority of these methods could lose the ref parameter. 我研究了很多代码,其中大多数方法可能会丢失ref参数。 Although the code functions fine, I was wondering what kind of performance hit there might be by double dereferencing every argument rather than just passing the reference by value. 尽管代码功能正常,但我想知道通过双重取消对每个参数的引用而不是仅按值传递引用会带来什么样的性能下降。

For example, this code: 例如,此代码:

public void EmptyList(ref List<string> test)
{
    test.Clear();
}

VS this: VS这:

public void EmptyList(List<string> test)
{
    test.Clear();
}

EDIT 编辑

After reading what Nicholas Carey had to say, I tried the same thing with the code above. 阅读了尼古拉斯·凯里(Nicholas Carey)所说的内容之后,我尝试了上面的代码。 This was the resulting assembly: 这是产生的程序集:

            EmptyList(ref List<string> test)
00000028  mov         eax,dword ptr [ebp-40h] 
0000002b  mov         ecx,dword ptr [eax] 
0000002d  cmp         dword ptr [ecx],ecx 
0000002f  call        719210C4


            EmptyList(List<string> test)
00000028  mov         ecx,dword ptr [ebp-40h] 
0000002b  cmp         dword ptr [ecx],ecx 
0000002d  call        71920FD4 

The difference calling by explicit reference and calling by implicit reference is the difference between the lea (Load Effective Address) instruction and the mov ('Move') instruction. 通过显式引用调用和通过隐式引用调用的差异是lea (加载有效地址)指令与mov (“移动”)指令之间的差异。

AFAIK, on any modern processor, both of these instructions, in the form used, execute in a single clock cycle, so the difference is pretty much moot. 在任何现代处理器上,AFAIK均以所使用的形式将这两个指令在单个时钟周期内执行,因此两者之间的差异几乎没有意义。

Here's the code generated (debug mode) for the call by [explicit] reference: 这是[explicit]参考为调用生成的代码(调试模式):

            FooBar( ref o ) ;
00000035  lea         ecx,[ebp-40h] 
00000038  call        FFD0B008 
0000003d  nop 

And here's the code generated (debug mode) for the call by [implicit] reference: 这是[隐式]参考为调用生成的代码(调试模式):

            FooBar( o ) ;
0000003a  mov         ecx,dword ptr [ebp-40h] 
0000003d  call        FFD3B008 
00000042  nop 

The code generated for the called method/function is identical in either case. 在两种情况下,为被调用方法/函数生成的代码都是相同的。

Here's the sample code I used, FWIW: 这是我使用的示例代码FWIW:

class Program
{
  static void Main( string[] args )
  {
    object o = null ;
    FooBar( ref o ) ;
  }

  private static void FooBar( ref object o )
  {
  }

}

IMHO, omit the ref keyword unless it's actually needed: all it really does is add semantic noise to the equation. 恕我直言,除非实际需要,否则请省略ref关键字:它真正要做的只是在等式中增加语义干扰。

The performance difference would likely be completely unnoticed, if it exists at all. 如果根本不存在性能差异,则可能完全没有注意到。 I would personally decide whether to pass the "reference parameters" by reference or by value by functional requirements , not performance differences. 我将亲自决定是通过引用还是通过功能需求 (而不是性能差异)通过值传递“参考参数”。

Passing a reference type using ref has a strong implication to the caller. 使用ref传递引用类型对调用者有很大的影响。 The assumption is that your reference may change. 假设您的参考可能会更改。 This has a distinct implication to the usage of your API, and a strong suggestion that you may be changing values. 这对您的API的使用有明显的暗示,强烈建议您可能要更改值。 If this is not the case, pass the reference by value to avoid the confusion, as it will lead to more maintainable, understandable code. 如果不是这种情况,请按值传递引用以避免混淆,因为这将导致更易于维护和理解的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM