3
我得到了從this post和this一個子字符串struct
的想法。第二篇文章是.net的String.GetHashCode()的實現。 (我不確定哪個版本的.net來自於此。)什麼導致GetHashCode的這個實現比.net的實現慢20倍?
這是實現。 (GetHashCode的從上面列出的第二源獲得。)
public struct Substring
{
private string String;
private int Offset;
public int Length { get; private set; }
public char this[int index] { get { 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;
for (int i = Length; i > 0; i -= 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));
}
}
}
這裏的一個單元測試:
[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 is jitted
var count = 100000000;
var sw = Stopwatch.StartNew();
for (var i = 0; i < count; ++i)
sum += t.GetHashCode();
var t1 = sw.Elapsed;
sw = Stopwatch.StartNew();
for (var i = 0; i < count; ++i)
sum += sub.GetHashCode();
var t2 = sw.Elapsed;
Debug.WriteLine(sum.ToString()); // make sure we use the return value
var m1 = t1.Milliseconds;
var m2 = t2.Milliseconds;
Assert.IsTrue(m2 <= m1); // fat chance
}
的問題是,m1爲10毫秒和m2是190毫秒。 (注意:這是1000000個迭代。)僅供參考,我在.net 4.5 64位版本上運行了這個版本,打開了Optimizations。
與問題無關,但是您是否爲了節省內存而編寫了這個類? – Matthew 2014-09-10 18:14:18
您正在製造傳統的基準標記錯誤。就像在測量中包含點擊開銷一樣。而不是實際使用返回值,允許抖動優化器完全消除代碼。 – 2014-09-10 18:17:26
這是一個很好的觀點。所以我回去並在做任何時機之前添加了另一個sub.GetHashCode()循環。同樣的結果 - 毫秒。 – bright 2014-09-10 18:22:01