Search code examples
c#unsafe

Does the nesting of an 'unsafe' scope affects performance?


I would like to ask if the first example is somehow slower than the second example.

Example 1: for, unsafe, unsafe, unsafe, etc

for (var i = 0; i < ...; i++)
{
    unsafe
    {
        // ...
    }
}

Example 2: unsafe, for

unsafe
{
    for (var i = 0; i < ...; i++)
    {
        // ...
    }
}

Nowhere in the documentation this aspect is being covered.

Question:

Can someone assume than the location of an unsafe code block does not affect performance ?


Solution

  • They produce the exact same IL code so no performance difference

    nested: See on SharpLab

    c#

    using System;
    public class C {
        public void M() {
            var x = 0;
            for (var i = 0; i < 100; i++)
            {            
                unsafe { x+=i; }
            }
        }
    }
    

    IL

    .class private auto ansi '<Module>'
    {
    } // end of class <Module>
    
    .class public auto ansi beforefieldinit C
        extends [System.Private.CoreLib]System.Object
    {
        // Methods
        .method public hidebysig 
            instance void M () cil managed 
        {
            // Method begins at RVA 0x2050
            // Code size 20 (0x14)
            .maxstack 2
            .locals init (
                [0] int32,
                [1] int32
            )
    
            IL_0000: ldc.i4.0
            IL_0001: stloc.0
            IL_0002: ldc.i4.0
            IL_0003: stloc.1
            // sequence point: hidden
            IL_0004: br.s IL_000e
            // loop start (head: IL_000e)
                IL_0006: ldloc.0
                IL_0007: ldloc.1
                IL_0008: add
                IL_0009: stloc.0
                IL_000a: ldloc.1
                IL_000b: ldc.i4.1
                IL_000c: add
                IL_000d: stloc.1
    
                IL_000e: ldloc.1
                IL_000f: ldc.i4.s 100
                IL_0011: blt.s IL_0006
            // end loop
    
            IL_0013: ret
        } // end of method C::M
    
        .method public hidebysig specialname rtspecialname 
            instance void .ctor () cil managed 
        {
            // Method begins at RVA 0x2070
            // Code size 7 (0x7)
            .maxstack 8
    
            IL_0000: ldarg.0
            IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
            IL_0006: ret
        } // end of method C::.ctor
    
    } // end of class C
    

    surrounding: See on SharpLab

    c#

    using System;
    public class C {
        public void M() {
            var x = 0;
            unsafe {
                for (var i = 0; i < 100; i++)
                {            
                    x+=i;
                }
            }
        }
    }
    

    IL

    .class private auto ansi '<Module>'
    {
    } // end of class <Module>
    
    .class public auto ansi beforefieldinit C
        extends [System.Private.CoreLib]System.Object
    {
        // Methods
        .method public hidebysig 
            instance void M () cil managed 
        {
            // Method begins at RVA 0x2050
            // Code size 20 (0x14)
            .maxstack 2
            .locals init (
                [0] int32,
                [1] int32
            )
    
            IL_0000: ldc.i4.0
            IL_0001: stloc.0
            IL_0002: ldc.i4.0
            IL_0003: stloc.1
            // sequence point: hidden
            IL_0004: br.s IL_000e
            // loop start (head: IL_000e)
                IL_0006: ldloc.0
                IL_0007: ldloc.1
                IL_0008: add
                IL_0009: stloc.0
                IL_000a: ldloc.1
                IL_000b: ldc.i4.1
                IL_000c: add
                IL_000d: stloc.1
    
                IL_000e: ldloc.1
                IL_000f: ldc.i4.s 100
                IL_0011: blt.s IL_0006
            // end loop
    
            IL_0013: ret
        } // end of method C::M
    
        .method public hidebysig specialname rtspecialname 
            instance void .ctor () cil managed 
        {
            // Method begins at RVA 0x2070
            // Code size 7 (0x7)
            .maxstack 8
    
            IL_0000: ldarg.0
            IL_0001: call instance void [System.Private.CoreLib]System.Object::.ctor()
            IL_0006: ret
        } // end of method C::.ctor
    
    } // end of class C