Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In C#, Is it slower to reference an array variable?

Tags:

I've got an array of integers, and I'm looping through them:

for (int i = 0; i < data.Length; i++) {   // do a lot of stuff here using data[i] } 

If I do:

for (int i = 0; i < data.Length; i++) {   int value = data[i];   // do a lot of stuff with value instead of data[i] } 

Is there any performance gain/loss?

From my understanding, C/C++ array elements are accessed directly, i.e. an n-element array of integers has a contiguous memory block of length n * sizeof(int), and the program access element i by doing something like *data[i] = *data[0] + (i * sizeof(int)). (Please excuse my abuse of notation, but you get what I mean.)

So this means C/C++ should have no performance gain/loss for referencing array variables.

What about C#? C# has a bunch of extra overhead like data.Length, data.IsSynchronized, data.GetLowerBound(), data.GetEnumerator().

Clearly, a C# array is not the same as a C/C++ array.

So what's the verdict? Should I store int value = data[i] and work with value, or is there no performance impact?

like image 485
Ozzah Avatar asked Apr 07 '11 02:04

Ozzah


People also ask

What does != Mean in C?

The not-equal-to operator ( != ) returns true if the operands don't have the same value; otherwise, it returns false .

What is '~' in C programming?

In mathematics, the tilde often represents approximation, especially when used in duplicate, and is sometimes called the "equivalency sign." In regular expressions, the tilde is used as an operator in pattern matching, and in C programming, it is used as a bitwise operator representing a unary negation (i.e., "bitwise ...

What is & operator in C?

&& This is the AND operator in C programming language. It performs logical conjunction of two expressions. ( If both expressions evaluate to True, then the result is True. If either of the expression evaluates to False, then the result is False)

What is the use of in C?

In C/C++, the # sign marks preprocessor directives. If you're not familiar with the preprocessor, it works as part of the compilation process, handling includes, macros, and more.


1 Answers

You can have the cake and eat it too. There are many cases where the jitter optimizer can easily determine that an array indexing access is safe and doesn't need to be checked. Any for-loop like you got in your question is one such case, the jitter knows the range of the index variable. And knows that checking it again is pointless.

The only way you can see that is from the generated machine code. I'll give an annotated example:

    static void Main(string[] args) {         int[] array = new int[] { 0, 1, 2, 3 };         for (int ix = 0; ix < array.Length; ++ix) {             int value = array[ix];             Console.WriteLine(value);         }     }  Starting at the for loop, ebx has the pointer to the array:              for (int ix = 0; ix < array.Length; ++ix) { 00000037  xor         esi,esi                       ; ix = 0 00000039  cmp         dword ptr [ebx+4],0           ; array.Length < 0 ? 0000003d  jle         0000005A                      ; skip everything                 int value = array[ix]; 0000003f  mov         edi,dword ptr [ebx+esi*4+8]   ; NO BOUNDS CHECK !!!                 Console.WriteLine(value); 00000043  call        6DD5BE38                      ; Console.Out 00000048  mov         ecx,eax                       ; arg = Out 0000004a  mov         edx,edi                       ; arg = value 0000004c  mov         eax,dword ptr [ecx]           ; call WriteLine() 0000004e  call        dword ptr [eax+000000BCh]              for (int ix = 0; ix < array.Length; ++ix) { 00000054  inc         esi                           ; ++ix 00000055  cmp         dword ptr [ebx+4],esi         ; array.Length > ix ? 00000058  jg          0000003F                      ; loop 

The array indexing happens at address 00003f, ebx has the array pointer, esi is the index, 8 is the offset of the array elements in the object. Note how the esi value is not checked again against the array bounds. This runs just as fast as the code generated by a C compiler.

like image 102
Hans Passant Avatar answered Dec 29 '22 00:12

Hans Passant