Question

I want to implement a fast hash function that will use int datatype and rely on integer overflow. MSDN says that in order to guarantee that overflows don't trigger exceptions I have to use unchecked blocks for that code.

Suppose I surround only that computation in an unchecked block. Will my code have any performance or portability problems because of that?

Was it helpful?

Solution

Technically only the checked blocks should slow. So I don't think an unchecked block (a block where the framework has to do less checks) could slow. It isn't a context switch or something similar. The JIT simply doesn't emit instructions to check for overflow/underflow. Now, clearly if someone created a "special" processor where overflow must be simulated and ported Mono on it, or where an overflow causes different results than on Intel processors, an unchecked block would be slower (because the JIT would have to "simulate" it). But note that the base types of .NET are defined in the ECMA standard. Signed ints must be based on two-complement for example, and their size must be 8, 16, 32, 64 bits. There isn't much space for "strange" processors that use 36 bits integers.

OTHER TIPS

checked add only one process instruction:

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  
}

As a rule you can expect unchecked arithmetic to be slightly faster, but it's pretty much never worth asking the opposite question to yours (viz. "will using checked hurt my performance?").

Checked and unchecked just mean there are slightly different rules as to how operators like +, *, and - are treated, and you should use the one appropriate for the case in hand.

In this case, you quite definitely want unchecked, so you should state this in your code. This actually increases portability, since you will then have the same behaviour whatever compiler switches are used with it.

I've created two methods, one wrapped by checked and an other by unchecked. By looking into IL only one difference is mul operation (which does multiplication operation), for checked mul.ovf is generated and for unchecked - mul.

To summarize, I believe difference in a single CPU operation does not make any impact on performance, the only one difference would be in case of overflow using checked - in this case OverflowException will be generated which obviously slow down execution.

MSDN:

The following Microsoft intermediate language (MSIL) instructions throw an OverflowException:

  • 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(...)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top