简体   繁体   中英

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. 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:

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. 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.

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.

Here's the code generated (debug mode) for the call by [explicit] reference:

            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:

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.

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. 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. If this is not the case, pass the reference by value to avoid the confusion, as it will lead to more maintainable, understandable code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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