c# - What is causing this implementation of GetHashCode to be 20 times slower than .net's implementation? -
i got idea of substring struct
this post , this one. second post has implementation of .net's string.gethashcode(). (i'm not sure version of .net from.)
here implementation. (gethashcode taken second source listed above.)
public struct substring { private string string; private int offset; public int length { get; private set; } public char this[int index] { { return string[offset + index]; } } public substring(string str, int offset, int len) : this() { string = str; offset = offset; length = len; } /// <summary> /// see http://www.dotnetperls.com/gethashcode /// </summary> /// <returns></returns> public unsafe override int gethashcode() { fixed (char* str = string + offset) { char* chptr = str; int num = 352654597; int num2 = num; int* numptr = (int*)chptr; (int = length; > 0; -= 4) { num = (((num << 5) + num) + (num >> 27)) ^ numptr[0]; if (i <= 2) { break; } num2 = (((num2 << 5) + num2) + (num2 >> 27)) ^ numptr[1]; numptr += 2; } return (num + (num2 * 1566083941)); } } }
here's unit test:
[test] public void gethashcode_isasfastasstring() { var s = "the quick brown fox"; var sub = new substring(s, 1, 5); var t = "quick"; var sum = 0; sum += sub.gethashcode(); // make sure gethashcode jitted var count = 100000000; var sw = stopwatch.startnew(); (var = 0; < count; ++i) sum += t.gethashcode(); var t1 = sw.elapsed; sw = stopwatch.startnew(); (var = 0; < count; ++i) sum += sub.gethashcode(); var t2 = sw.elapsed; debug.writeline(sum.tostring()); // make sure use return value var m1 = t1.milliseconds; var m2 = t2.milliseconds; assert.istrue(m2 <= m1); // fat chance }
the problem m1 10 milliseconds , m2 190 milliseconds. (note: 1000000 iterations.) fyi, ran on .net 4.5 64 bit release build optimizations turned on.
- clued comment, double checked make sure optimized code running. turns out obscure debugger setting disabling optimizations. unchecked tools – options – debugging – general – suppress jit optimization on module load (managed only). caused optimized code load properly.
- even optimizations turned on there still 3x - 6x difference. however, might attributable fact code above .net 32 bit version , i'm running 64 bit .net. porting 64 bit implementation of string.gethashcode substring not easy because relies on 0 end of string marker (which in fact bug).
at time i'm disappointed not getting parity performance, excellent use of time in learning of perils , pitfalls of optimizing c#.
Comments
Post a Comment