none
Auto properties - performance hit RRS feed

  • Question

  • Hi,

    I've been using auto properties for a while and it just crossed my mind today if there is a performance hit associated with them when get/set is called within defining class or if the compiler optimizes properly and it looks like it doesn't.

    I define a test class like this:
        public class TestClass
    {
    public double Val1 { get; set; }

    private double val2;
    public double Val2
    {
    get { return val2; }
    set { val2 = value; }
    }

    public void SetValues()
    {
    Val1 = 1;
    val2 = 2;
    }
    }
    the compiler generates the following code:
    .class public auto ansi beforefieldinit TestClass
        extends [mscorlib]System.Object
    {
        .method public hidebysig specialname rtspecialname instance void .ctor() cil managed
        {
            .maxstack 8
            L_0000: ldarg.0 
            L_0001: call instance void [mscorlib]System.Object::.ctor()
            L_0006: ret 
        }
    
        .method public hidebysig instance void SetValues() cil managed
        {
            .maxstack 8
            L_0000: ldarg.0 
            L_0001: ldc.r8 1
            L_000a: call instance void ConsoleApplication15.TestClass::set_Val1(float64)
            L_000f: ldarg.0 
            L_0010: ldc.r8 2
            L_0019: stfld float64 ConsoleApplication15.TestClass::val2
            L_001e: ret 
        }
    
    
        .property instance float64 Val1
        {
            .get instance float64 ConsoleApplication15.TestClass::get_Val1()
            .set instance void ConsoleApplication15.TestClass::set_Val1(float64)
        }
    
        .property instance float64 Val2
        {
            .get instance float64 ConsoleApplication15.TestClass::get_Val2()
            .set instance void ConsoleApplication15.TestClass::set_Val2(float64)
        }
    
    
        .field private float64 <Val1>k__BackingField
        {
            .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
        }
    
        .field private float64 val2
    
    }
    
     
    
    So, if you look at the SetValues method it looks like the compiler doesn't optimize properly as it calls a call instance execution:
    L_000a: call instance void ConsoleApplication15.TestClass::set_Val1(float64)
    ... resulting in a performance hit over:
    L_0019: stfld float64 ConsoleApplication15.TestClass::val2
    when it could have optimized it to:
    _000a: stfld float64 void ConsoleApplication15.TestClass::k__BackingField

    Can someone shed some insight in why it is not doing that and confirm my conclusion that if high performance access is required to access local fields, auto-properties should be avoided?

    Thanks,

    Tom
    Thursday, May 28, 2009 5:00 PM

Answers

  • You are looking at the wrong code, it is not MSIL that runs.  The JIT compiler generates the actual machine code.  And it will inline any auto properties.  Not just that, it will inline the SetValues() method as well:

    00000000  push        rbx 
    00000001  sub         rsp,20h
    00000005  mov         rcx,7FF001D3228h
    0000000f  call        FFFFFFFFF013D9A0
    00000014  mov         rbx,rax
    00000017  mov         rcx,rbx
    0000001a  call        FFFFFFFFFFEC9AA8
                t.SetValues();
    0000001f  movsd       xmm0,mmword ptr [00000040h]
    00000027  movsd       mmword ptr [rbx+10h],xmm0
    0000002c  movsd       xmm0,mmword ptr [00000048h]
    00000034  movsd       mmword ptr [rbx+8],xmm0
    00000039  add         rsp,20h
    0000003d  pop         rbx 
    0000003e  rep ret    

    To see this kind of code yourself, you'll have to use the Release build and disable the "Suppress JIT optimization" option in the debugger settings.
    Hans Passant.
    • Marked as answer by Tom Frey Friday, May 29, 2009 12:27 AM
    Thursday, May 28, 2009 5:32 PM
    Moderator

All replies

  • fyi, I  just run a quick benchmark on the code as well and the "call instance" instruction runs 43% slower than "stfld float64" instruction on my test server
    Thursday, May 28, 2009 5:12 PM
  • You are looking at the wrong code, it is not MSIL that runs.  The JIT compiler generates the actual machine code.  And it will inline any auto properties.  Not just that, it will inline the SetValues() method as well:

    00000000  push        rbx 
    00000001  sub         rsp,20h
    00000005  mov         rcx,7FF001D3228h
    0000000f  call        FFFFFFFFF013D9A0
    00000014  mov         rbx,rax
    00000017  mov         rcx,rbx
    0000001a  call        FFFFFFFFFFEC9AA8
                t.SetValues();
    0000001f  movsd       xmm0,mmword ptr [00000040h]
    00000027  movsd       mmword ptr [rbx+10h],xmm0
    0000002c  movsd       xmm0,mmword ptr [00000048h]
    00000034  movsd       mmword ptr [rbx+8],xmm0
    00000039  add         rsp,20h
    0000003d  pop         rbx 
    0000003e  rep ret    

    To see this kind of code yourself, you'll have to use the Release build and disable the "Suppress JIT optimization" option in the debugger settings.
    Hans Passant.
    • Marked as answer by Tom Frey Friday, May 29, 2009 12:27 AM
    Thursday, May 28, 2009 5:32 PM
    Moderator