How does the C # compiler optimize a piece of code?

If I have a code like this

for(int i=0;i<10;i++)
{
    int iTemp;
    iTemp = i;
    //.........
}

Does the compiler create iTemp 10 times?

Or is he optimizing it?

I mean, if I rewrite the loop as

int iTemp;
for(int i=0;i<10;i++)
{
    iTemp = i;
    //.........
}

Will it be faster?

+3
source share
7 answers

Using reflector , you can view the IL generated by the C # compiler.

.method private hidebysig static void Way1() cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 i)
    L_0000: ldc.i4.0 
    L_0001: stloc.0 
    L_0002: br.s L_0008
    L_0004: ldloc.0 
    L_0005: ldc.i4.1 
    L_0006: add 
    L_0007: stloc.0 
    L_0008: ldloc.0 
    L_0009: ldc.i4.s 10
    L_000b: blt.s L_0004
    L_000d: ret 
}

.method private hidebysig static void Way2() cil managed
{
    .maxstack 2
    .locals init (
        [0] int32 i)
    L_0000: ldc.i4.0 
    L_0001: stloc.0 
    L_0002: br.s L_0008
    L_0004: ldloc.0 
    L_0005: ldc.i4.1 
    L_0006: add 
    L_0007: stloc.0 
    L_0008: ldloc.0 
    L_0009: ldc.i4.s 10
    L_000b: blt.s L_0004
    L_000d: ret 
}

They are exactly the same, so they have no performance difference when you declare iTemp.

+20
source

, , , IL, , . , . , .

, .

Try:

var a = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

var q = a.AsEnumerable();
int iTemp;
for(int i=0;i<10;i++) 
{ 
    iTemp = i;
    q = q.Where( x => x <= iTemp );
}

Console.WriteLine(string.Format( "{0}, count is {1}",
    string.Join( ":", q.Select( x => x.ToString() ).ToArray() ),
    q.Count() ) );

var a = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

var q = a.AsEnumerable();
for(int i=0;i<10;i++) 
{ 
    var iTemp = i;
    q = q.Where( x => x <= iTemp );
}

Console.WriteLine(string.Format( "{0}, count is {1}",
    string.Join( ":", q.Select( x => x.ToString() ).ToArray() ),
    q.Count() ) );
+4

, CSC ( #) , LINQPad - , , # IL (- CLR).

+3

, . , , - , .

:

int Func(int a, int b, int c)
{
    int x = a * 2;
    int y = b * 3;
    int z = c * 4;
    return x + y + z;
 }

, (a * 2) + (b * 3) + (c * 4), .

:

int Func(int a, int b, int c)
{
    int x = a * 2;
    {
        int y = b * 3;
        {
            int z = c * 4;
            {
                return x + y + z;
            }
        }
     }
 }

3 - . for - , , .

:

int Func(int a, int b, int c)
{
    int x = a * 2;
    {
        int y = b * 3;
        x += y;
    }
    {
        int z = c * 4;
        x += z;
    }
    return x;
}

, . y z, - , , . , y z . , , - ​​ , , .NET.

, # VS2008 . IL :

L_0000: ldarg.0 
L_0001: ldc.i4.2 
L_0002: mul 
L_0003: stloc.0 
L_0004: ldarg.1 
L_0005: ldc.i4.3 
L_0006: mul 
L_0007: stloc.1 
L_0008: ldarg.2 
L_0009: ldc.i4.4 
L_000a: mul 
L_000b: stloc.2 
L_000c: ldloc.0 
L_000d: ldloc.1 
L_000e: add 
L_000f: ldloc.2 
L_0010: add 
L_0011: ret 

:

L_0000: ldarg.0 
L_0001: ldc.i4.2 
L_0002: mul 
L_0003: ldarg.1 
L_0004: ldc.i4.3 
L_0005: mul 
L_0006: add 
L_0007: ldarg.2 
L_0008: ldc.i4.4 
L_0009: mul 
L_000a: add 
L_000b: ret 
+3

, .

.

+1

IL, , . , , . .

, , , , , , , .

, , iTemp, , , 32 iTemp. , iTemp ; , iTemp for . , , ( ) .

0

# . JIT IL, #, IL () .

Take an earlier example:

static int Func(int a, int b, int c)
{
    int x = a * 2;
    int y = b * 3;
    int z = c * 4;
    return x + y + z;
}

The emitted IL from compiler 3.5 with optimizations turned on is as follows:

.method private hidebysig static int32  Func(int32 a,
                                             int32 b,
                                             int32 c) cil managed
{
  // Code size       18 (0x12)
  .maxstack  2
  .locals init (int32 V_0,
           int32 V_1,
           int32 V_2)
  IL_0000:  ldarg.0
  IL_0001:  ldc.i4.2
  IL_0002:  mul
  IL_0003:  stloc.0
  IL_0004:  ldarg.1
  IL_0005:  ldc.i4.3
  IL_0006:  mul
  IL_0007:  stloc.1
  IL_0008:  ldarg.2
  IL_0009:  ldc.i4.4
  IL_000a:  mul
  IL_000b:  stloc.2
  IL_000c:  ldloc.0
  IL_000d:  ldloc.1
  IL_000e:  add
  IL_000f:  ldloc.2
  IL_0010:  add
  IL_0011:  ret
} // end of method test::Func

Not very optimal? I compile it into an executable, calling it from a simple Main method, and the compiler does not insert it or does any optimizations really.

So what happens at runtime?

JIT actually points to a Func () call and gives much better code than you can imagine by looking at the IL based on the stack above:

mov     edx,dword ptr [rbx+10h]
mov     eax,1
cmp     rax,rdi
jae     000007ff`00190265

mov     eax,dword ptr [rbx+rax*4+10h]
mov     ecx,2
cmp     rcx,rdi
jae     000007ff`00190265

mov     ecx,dword ptr [rbx+rcx*4+10h]
add     edx,edx
lea     eax,[rax+rax*2]
shl     ecx,2
add     eax,edx
lea     esi,[rax+rcx]
0
source

Source: https://habr.com/ru/post/1726980/


All Articles