2010-08-18 76 views
2

我有一個問題,我需要能夠在javascript和C#中爲GUID生成相同的均勻分佈的數值哈希值。我想這會阻止我在C#中使用Guid.GetHashCode(),因爲我無法在沒有反向工程C#的情況下重現JS中的行爲。在C#和javascript中引導的相同哈希值

是否有快速從JS中的guids/strings生成哈希的方法?這些字符串的所有數字是否均勻分佈在.NET生成的GUID中?我應該只是將尾部字符轉換爲int?

回答

5

字節顯然不均勻分佈。

我把一些代碼來品嚐.NET的GUID並繪製分佈:

的所有測試代碼首先,這造成百萬的GUID,並計算不同值的數量爲字節數組中的每個字節。它將它全部輸出到我在Scilab中繪製的矩陣中。

int[,] counter = new int[16, 256]; 
for (int i = 0; i < 1000000; i++) 
{ 
    var g = Guid.NewGuid(); 
    var bytes = g.ToByteArray(); 
    for (int idx = 0; idx < 16; idx++) 
    { 
     counter[idx, bytes[idx]]++; 
    } 
} 
StringBuilder sb = new StringBuilder(); 
sb.AppendLine("x = ["); 
for (int idx = 0; idx < 16; idx++) 
{ 
    for (int b = 0; b < 256; b++) 
    { 
     sb.Append(counter[idx, b]); 
     if (idx != 255) 
     { 
      sb.Append(" "); 
     } 
    } 
    if (idx != 15) 
    { 
     sb.AppendLine(";"); 
    } 
} 
sb.AppendLine("]"); 

File.WriteAllText("plot.sce", sb.ToString()); 

這裏有分佈,曲線繪製每個不同的值的數目對於每個字節數組中的位置中的:

的字節數組中的位置0-6的值分佈: The value distribution for the positions 0-6 in the byte array
字節數組中的位置7值分佈:
The value distribution for the position 7 in the byte array
字節數組中的位置8值分佈:
The value distribution for the position 8 in the byte array
的字節數組中的位置9-15的值分佈: The value distribution for the positions 9-15 in the byte array

對於字節位置0-6和9-15值的分佈似乎是均勻,但對於字節位置7和8中分銷相當有限。

也就是說,對於GUID(與下面的字節位置開始時,注意到奇怪排序)

{1369ea05-b9f9-408b-ac7c-7ebd0f35d562} 
         1 1 1 1 1 1 
3 2 1 0 5 4 7 6 8 9 0 1 2 3 4 5 

位置7可以取值從64(0×40)至79(0x4F)。
位置8可以取值從128(0x80)到191(0xBF)。
其餘字節均勻分佈。

注意:測試是在32位Windows 7機器上的.NET4上運行的。

教訓:不要假設的東西,測試。

答案:要使用.NET Guids來計算負載平衡,您可以使用除上述Guid中標記爲7和8的位置以外的任何部分。

問題:有誰知道爲什麼分配不均勻分佈?

+0

哇,Albin。你贏了!非常感謝你。順便說一句:關於這個答案的評論提供了一個線索,爲什麼比特在7和8位不統一:http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-的JavaScript/105074#105074。也許有些位提供了有關GUID的生成方法/出處的詳細信息? – 2010-08-19 23:48:28

+0

啊,一些版本信息和一些算法選擇的標記。 – 2010-08-20 04:58:08

2

你可以創建一個Web服務來在服務器端生成哈希值,使用任何你想要的語言。在客戶端,簡單的Web服務調用就可以實現。

+1

我之後很快 - 我需要避免往返於服務器或服務器機器之間。這是爲了允許一種負載平衡,它不需要硬件,這將允許我的Ajax應用程序在無需等待的情況下優雅地故障轉移。 – 2010-08-18 05:51:32

+0

計算guid散列的目的是什麼?你想使用它進行負載平衡嗎? – 2010-08-18 16:28:19

+0

我需要它能夠識別(從服務器端或客戶端的任何地方)IIS服務器的特定子集,以傳遞緩存數據,以便爲來自UI的傳入請求做好準備。 – 2010-08-18 23:00:26

1

反射說,.NET Guid.GetHashCode()被這樣

public override int GetHashCode() 
{ 
    return ((this._a^((this._b << 0x10) | ((ushort) this._c)))^((this._f << 0x18) | this._k)); 
} 

_a,_b,_c實現和_f是在構造函數中定義取字節[16]數組

public Guid(byte[] b) 
{ 
    if (b == null) 
    { 
     throw new ArgumentNullException("b"); 
    } 
    if (b.Length != 0x10) 
    { 
     throw new ArgumentException(Environment.GetResourceString("Arg_GuidArrayCtor", new object[] { "16" })); 
    } 
    this._a = (((b[3] << 0x18) | (b[2] << 0x10)) | (b[1] << 8)) | b[0]; 
    this._b = (short) ((b[5] << 8) | b[4]); 
    this._c = (short) ((b[7] << 8) | b[6]); 
    this._d = b[8]; 
    this._e = b[9]; 
    this._f = b[10]; 
    this._g = b[11]; 
    this._h = b[12]; 
    this._i = b[13]; 
    this._j = b[14]; 
    this._k = b[15]; 
} 
+0

在JS中是否有一個基於非字符串的GUID表示?我懷疑,如果有更直接的方法從字符串創建一個好的散列,那麼將字符串(我將接收)轉換爲字節數組,並從那裏轉換爲GUID以生成int將是浪費的表示。 – 2010-08-18 22:58:14

+0

要創建一個負載均衡索引,這似乎是矯枉過正。轉換爲字節只需將字母2和2分組並將其解析爲十六進制值。如果數字和它看起來像一些字節比其他更常見,我已經做了一些測試與分佈,但我必須查看更多的細節之前,我可以發佈有關的任何東西的差異。 – 2010-08-19 05:24:29

相關問題