Insecure C # performance, removes long listing in int to access array index

Hi, I got the following code in C # insecure, where the array is fixed.

array[(int)(index)] 

the index is long (and should be long for some reason). So I need to pass it to int in order to access the array element. Is there a way to use pointers or some other combination of actions in unsafe code to prevent this casting reason index from having a long value of 1, for example (and never exceed int obv). I feel that possibly unsafe pointers can interfere with this. I also feel that this actor is not free ... and the performance is here. (this line exactly) I also think that this is impossible, but I ask you to make a mistake just in case.

Ok, give a few details, I am doing some necessary logical operations for a long preIndex, for example

value = array [(int) ((preIndex and mask) β†’ 10)]

these operations are required, and the code is already minimalistic. The only thing I can find to be optimizable is to drop from long to int, cause bitwise operations.

thanks

+4
source share
5 answers

Yes, there is a trivial cost conversion from long to int , but I am sure that a: it will not be in any robust code and b: it is inevitable (access to arrays is via int index, period). To show the value will not be :

 static class Program { static int GetSize() { return 10000; } static void Main() { int size = GetSize(); int[] someData = new int[size]; var watchInt32 = Stopwatch.StartNew(); for (int i = 0; i < 5000; i++) { for (int j = 0; j < size; j++) { someData[j]++; } } for (int j = 0; j < size; j++) someData[j] = 0; watchInt32.Stop(); long lSize = size; var watchInt64 = Stopwatch.StartNew(); for (int i = 0; i < 5000; i++) { for (long j = 0; j < lSize; j++) { someData[j]++; } } watchInt64.Stop(); Console.WriteLine("{0}ms vs {1}ms over {2} iterations", (int)watchInt32.ElapsedMilliseconds, (int)watchInt64.ElapsedMilliseconds, 5000 * size); } } 

I get:

162ms vs 215ms for 50,000,000 iterations

Therefore, if your code does nothing but access the array, it just doesn't matter. At all. In a significant way.

+2
source

In an unchecked context (default), a cast will simply discard unnecessary MSBs, so there is no performance penalty. In a checked context, it throws an exception if the index range exceeds int.MaxValue .

+3
source

I don’t think you need to worry about the possible performance impact due to conversion. Just look at the machine code generated by the JIT, they are identical for the int and long index:

x86, release mode, int index:

  var val = arr[idx]; 00000059 cmp ebx,dword ptr [edx+4] 0000005c jae 00000078 0000005e mov esi,dword ptr [edx+ebx*4+8] 


x86, release mode, cast long index:

  var val = arr[(int)idx]; 0000005f cmp ebx,dword ptr [edx+4] 00000062 jae 00000081 00000064 mov esi,dword ptr [edx+ebx*4+8] 

x64, release mode, int index:

  var val = arr[idx]; 00000060 movsxd rcx,ebx 00000063 mov rax,qword ptr [rdi+8] 00000067 cmp rcx,3 0000006b jae 0000000000000080 0000006d mov ecx,dword ptr [rdi+rcx*4+10h] 


x64, release mode, long index:

  var val = arr[(int)idx]; 00000061 movsxd rcx,ebx 00000064 mov rax,qword ptr [rdi+8] 00000068 cmp rcx,3 0000006c jae 0000000000000080 0000006e mov ecx,dword ptr [rdi+rcx*4+10h] 

As Daniel Gehriger noted, the conv.i4 IL instruction should not be counted in machine code, 32 MSBs are simply discarded.

+1
source

The performance problem that you see from this line is related to index search - is it a regular array, for example object []? or did you implement the index property?

-1
source
 int count = 10000000; object [] a = new object[count]; Stopwatch s1 = Stopwatch.StartNew(); for (long i = 0; i < count; i++) a[i] = new object(); s1.Stop(); Stopwatch s2 = Stopwatch.StartNew(); for (int i = 0; i < count; i++) a[i] = new object(); s2.Stop(); Debug.WriteLine(s1.ElapsedTicks + " " + s2.ElapsedTicks); 

3362502 3115428

Thus, it has no significant effect.

-1
source

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


All Articles