Does an uncontrolled context use performance or portability in C #?

I want to implement a fast hash function that will use the int data type and rely on integer overflow. MSDN says that in order to ensure that the overflow does not throw an exception, I have to use unchecked blocks for this code.

Suppose I surround only this calculation in an unchecked block. Will my code have performance or portability issues because of this?

+6
source share
4 answers

Technically, only checked blocks should slow down. Therefore, I do not think that the unchecked block (the block where the framework should do fewer checks) may slow down. This is not a context switch or something like that. JIT simply does not generate instructions for checking overflow / underflow. Now it’s clear that if someone created a β€œspecial” processor where the overflow must be modeled and transferred to Mono, or when the overflow produces different results than Intel processors, the unchecked block will be slower (because JIT will have to be "mimicked" his). But note that the basic .NET types are defined in the ECMA standard. Signed ints should be based on a two-complement, for example, and their size should be 8, 16, 32, 64 bits. There is not much room for β€œweird” processors that use 36 bit integers .

+6
source

As a rule, you can expect that uncontrolled arithmetic will be a little faster, but to a large extent you should never ask the opposite question to yours (namely, "will it check the damage to my performance?").

Checked and not checked, just means that there are slightly different rules regarding how operators such as + , * and - are handled, and you must use the one that is appropriate for the case in question.

In this case, you absolutely definitely want to uncheck the box, so you must specify this in your code. This actually increases portability, since then you will have the same behavior as any compiler switches.

+7
source

I created two methods, one of which completed checked , and the other unchecked . When searching in IL, only one difference is the mul operation (which performs the multiplication operation), for the marked mul.ovf generated for unchecked - mul .

To summarize, I believe that the difference in one CPU operation does not affect performance, the only difference would be in the case of overflow using checked - in this case an OverflowException would be thrown, which would obviously slow down the execution.

MSDN:

The following Microsoft Intermediate Language (MSIL) statements throw overceptionException:

  • mul.ovf.
  • ...
 [Test] public void Checked() { checked { int i = int.MaxValue; i = i * 100; Debug.WriteLine(i); } } [Test] public void UnChecked() { unchecked { int i = int.MaxValue; i = i * 100; Debug.WriteLine(i); } } 

And then using ILDASM, see IL:

CHECKED ():

 // Code size 27 (0x1b) .maxstack 2 .locals init ([0] int32 i) IL_0000: nop IL_0001: nop IL_0002: ldc.i4 0x7fffffff IL_0007: stloc.0 IL_0008: ldloc.0 IL_0009: ldc.i4.s 100 **IL_000b: mul.ovf** !!! IL_000c: stloc.0 IL_000d: ldloc.0 IL_000e: box [mscorlib]System.Int32 IL_0013: call void [System]System.Diagnostics.Debug::WriteLine ... 

UNCHECKED ():

  // Code size 27 (0x1b) .maxstack 2 .locals init ([0] int32 i) IL_0000: nop IL_0001: nop IL_0002: ldc.i4 0x7fffffff IL_0007: stloc.0 IL_0008: ldloc.0 IL_0009: ldc.i4.s 100 **IL_000b: mul** !!! IL_000c: stloc.0 IL_000d: ldloc.0 IL_000e: box [mscorlib]System.Int32 IL_0013: call void [System]System.Diagnostics.Debug::WriteLine(...) 
+4
source

checked adds only one process command:

 checked { int y = x * x; 05297978 mov eax,dword ptr [ebp-10h] 0529797B imul eax,dword ptr [ebp-10h] 0529797F jno 05297986 //if not overflow: goto 05297986 05297981 call 72A29522 //invoke exception 05297986 mov dword ptr [ebp-14h],eax } unchecked { int yy = xx * xx; 0529799E mov eax,dword ptr [ebp-18h] 052979A1 imul eax,dword ptr [ebp-18h] 052979A5 mov dword ptr [ebp-1Ch],eax } 
+3
source

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


All Articles