Vaut-il la peine d'enregistrer la longueur d'un tableau dans une variable locale en C #

Très souvent, je remarque que les gens écrivent comme ceci:

var length = array.Length;
for (int i = 0; i < length; i++) {
    //do smth
}

, CLR Array.Length. .

C#:

public int WithoutVariable() {
    int sum = 0;
    for (int i = 0; i < array.Length; i++) {
        sum += array[i];
    }
    return sum;
}
public int WithVariable() {
    int sum = 0;
    int length = array.Length;
    for (int i = 0; i < length; i++) {
        sum += array[i];
    }
    return sum;
}

, JIT .NET Framework 4.7.2 LegacyJIT-x86:
WithoutVariable()
;int sum = 0;
    xor  edi, edi
;int i = 0;
    xor  esi, esi
;int[] localRefToArray = this.array;
    mov  edx, dword ptr [ecx+4]
;int arrayLength = localRefToArray.Length;
    mov  ecx, dword ptr [edx+4]
;if (arrayLength == 0) return sum;
    test ecx, ecx
    jle  exit
;int arrayLength2 = localRefToArray.Length;
    mov  eax, dword ptr [edx+4] 
;if (i >= arrayLength2)
;  throw new IndexOutOfRangeException();
  loop:
    cmp  esi, eax
    jae  056e2d31
;sum += localRefToArray[i];
    add  edi, dword ptr [edx+esi*4+8]
;i++;
    inc  esi
;if (i < arrayLength) goto loop
    cmp  ecx, esi
    jg  loop
;return sum;
  exit:
    mov  eax, edi
WithVariable()
;int sum = 0;
    xor  esi, esi
;int[] localRefToArray = this.array;
    mov  edx, dword ptr [ecx+4]
;int arrayLength = localRefToArray.Length;
    mov  edi, dword ptr [edx+4]
;int i = 0;
    xor  eax, eax
;if (arrayLength == 0) return sum;
    test edi, edi
    jle  exit
;int arrayLength2 = localRefToArray.Length;
    mov  ecx, dword ptr [edx+4]
;if (i >= arrayLength2)
;  throw new IndexOutOfRangeException();
  loop:
    cmp  eax, ecx
    jae  05902d31
;sum += localRefToArray[i];
    add  esi, dword ptr [edx+eax*4+8]
;i++;
    inc  eax
;if (i < arrayLength) goto loop
    cmp  eax, edi
    jl   loop
;return sum;
  exit:
    mov  eax, esi

Meld


, — 15 . . . , :

  • 0 (arrayLength);
  • (arrayLength2);

, , .

:

public int WithoutVariable() {
    int sum = 0;
    for(int i = 0; i < array.Length; i++) {
        sum += array[i] + array.Length;
    }
    return sum;
}

public int WithVariable() {
    int sum = 0;
    int length = array.Length;
    for(int i = 0; i < length; i++) {
        sum += array[i] + length;
    }
    return sum;
}

, , . :
WithoutVariable()
int sum = 0;
    xor  edi, edi
int i = 0
    xor  esi, esi
int[] localRefToArray = this.array
    mov  edx, dword ptr [ecx+4]
int arrayLength = localRefToArray.Length
    mov  ebx, dword ptr [edx+4]
if (arrayLength == 0) return sum;
    test ebx, ebx
    jle  exit
int arrayLength2 = localRefToArray.Length;
    mov  ecx, dword ptr [edx+4]
if (i >= arrayLength2)
  throw new IndexOutOfRangeException()
  loop:
    cmp  esi, ecx 
    jae  05562d39
int t = array[i]
    mov  eax, dword ptr [edx+esi*4+8]
+= sum;
    add  eax, edi
t+= arrayLength;
    add  eax, ebx
sum = t
    mov  edi, eax
i++;
    inc  esi
if (i < arrayLength) goto loop
    cmp  ebx, esi
    jg   loop
return sum;
  exit:
    mov  eax, edi
WithVariable()
int sum = 0;
    xor  esi, esi
int[] localRefToArray = this.array;  
    mov  edx, dword ptr [ecx+4]
int arrayLength = localRefToArray.Length;  
    mov  ebx, dword ptr [edx+4]
int i = 0;  
    xor  ecx, ecx
if (arrayLength == 0) (return sum;) 
    test  ebx, ebx
    jle  exit
int arrayLength2 = localRefToArray.Length;
    mov   edi, dword ptr [edx+4]
if (i >= arrayLength2)
 throw new IndexOutOfRangeException();
 loop:
    cmp  ecx, edi
    jae  04b12d39
int t = array[i]
    mov  eax, dword ptr [edx+ecx*4+8]
+= sum
    add  eax, esi
t+= arrayLength
    add  eax, ebx
sum = t
    mov  esi, eax
i++
    inc  ecx
if (i < arrayLength) goto loop 
    cmp  ecx, ebx
    jl   loop
return sum;
  exit:
    mov  eax, esi

Meld


, . , sum array.Length, . :
int arrayLength2 = localRefToArray.Length;
    mov     edi, dword ptr [edx+4]
if (i >=arrayLength2) throw new IndexOutOfRangeException();
    cmp     ecx, edi
    jae     04b12d39
— .

, , .. . .

ForEach. :

public int ForEachWithoutLength() {
    int sum = 0;
    foreach (int i in array) {
        sum += i;
    }
    return sum;
}

public int ForEachWithLengthWithoutLocalVariable() {
    int sum = 0;
    foreach (int i in array) {
        sum += i + array.Length;
    }
    return sum;
}

public int ForEachWithLengthWithLocalVariable() {
    int sum = 0;
    int length = array.Length;
    foreach (int i in array) {
        sum += i + length;
    }
    return sum;
}

JIT:

ForEachWithoutLength()
;int sum = 0;
    xor  esi, esi
;int[] localRefToArray = this.array; 
    mov  ecx, dword ptr [ecx+4]
;int i = 0;
    xor  edx, edx
;int arrayLength = localRefToArray.Length; 
    mov  edi, dword ptr [ecx+4]
;if (arrayLength == 0) goto exit;
    test  edi, edi
    jle  exit
;int t = array[i];
  loop:
    mov  eax, dword ptr [ecx+edx*4+8]
;sum+=i;
    add  esi, eax
;i++;
    inc  edx
;if (i < arrayLength) goto loop
    cmp  edi, edx
    jg  loop
;return sum;
  exit:
    mov  eax, esi

ForEachWithLengthWithoutLocalVariable()
;int sum = 0;
    xor  esi, esi
;int[] localRefToArray = this.array;  
    mov  ecx, dword ptr [ecx+4]
;int i = 0; 
    xor  edx, edx
;int arrayLength = localRefToArray.Length;  
    mov  edi, dword ptr [ecx+4]
;if (arrayLength == 0) goto exit
    test  edi, edi
    jle  exit
;int t = array[i];  
  loop:
    mov  eax, dword ptr [ecx+edx*4+8]
;sum+=i; 
    add  esi, eax
;sum+=localRefToArray.Length;
    add  esi, dword ptr [ecx+4]
;i++;
    inc  edx
;if (i < arrayLength) goto loop 
    cmp  edi, edx
    jg  loop
;return sum;
  exit:
    mov  eax, esi

ForEachWithLengthWithLocalVariable()
;int sum = 0;
    xor  esi, esi
;int[] localRefToArray = this.array;   
    mov  edx, dword ptr [ecx+4]
;int length = localRefToArray.Length;   
    mov  ebx, dword ptr [edx+4]
;int i = 0;  
    xor  ecx, ecx
;int arrayLength = localRefToArray.Length;   
    mov  edi, dword ptr [edx+4]
;if (arrayLength == 0) goto exit; 
    test  edi, edi
    jle  exit
;int t = array[i];  
  loop: 
    mov  eax, dword ptr [edx+ecx*4+8]
;sum+=i;  
    add  esi, eax
;sum+=length ; 
    add  esi, ebx
;i++; 
    inc  ecx
;if (i < arrayLength) goto loop
    cmp  edi, ecx
    jg  loop
;return sum;
  exit:
    mov  eax, esi

, , for ( foreach 12 , for 15).

For ForEach


, for vs foreach 1 000 000 ,

sum+=array[i];
MethodItemsCountMeanErrorStdDevMedianRatioRatioSD
ForEach10000001.401 ms0.2691 ms0.7935 ms1.694 ms1.000.00
For10000001.586 ms0.3204 ms0.9447 ms1.740 ms1.230.65


sum+=array[i] + array.Length;
MethodItemsCountMeanErrorStdDevMedianRatioRatioSD
ForEach10000001.703 ms0.3010 ms0.8874 ms1.726 ms1.000.00
For10000001.715 ms0.2859 ms0.8430 ms1.956 ms1.130.56
ForEach For. ? JIT.

foreach


ForEachWithoutLength. . ForEach - , - . - JIT .

ForEachWithLengthWithoutLocalVariable. , sum+=length arrayLength, , . , N + 1, N — .

ForEachWithLengthWithLocalVariable. ForEachWithLengthWithoutLocalVariable, . arrayLength, , length . , . .

. , , , : . , , Foreach For.

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


All Articles