2012-04-01 205 views
2

有詞典< Int64,字節>被大量使用。我的意思是在大數據負載下運行數日的循環。 Int64來自兩個Int32。該字節恰好是來自許多非常長列表的這兩個Int32之間的距離(計數)。將兩個Int32結合到Int64中

我需要在這個循環做的是

  • 生成密鑰
  • 如果鍵不存在於字典然後插入鍵和值
  • 如果鍵不存在,新的值(字節)小於現有值,則用新值替換現有值

現在我正在使用直數學生成密鑰,我知道有更快的方法,但我無法想象它出。我把換檔作爲標籤,因爲我認爲這是如何優化它,但我無法弄清楚。

然後,當循環完成時,我需要從Int64中提取兩個Int32以將數據插入到數據庫中。

感謝

根據註釋我用的是數學兩個​​的Int32組合成一個Int64的

 Int64 BigInt; 
     Debug.WriteLine(Int32.MaxValue); 
     Int32 IntA = 0; 
     Int32 IntB = 1; 
     BigInt = ((Int64)IntA * Int32.MaxValue) + IntB; 
     Debug.WriteLine(BigInt.ToString()); 
     IntA = 1; 
     IntB = 0; 
     BigInt = ((Int64)IntA * Int32.MaxValue) + IntB; 
     Debug.WriteLine(BigInt.ToString()); 
     IntA = 1; 
     IntB = 1; 
     BigInt = ((Int64)IntA * Int32.MaxValue) + IntB; 
     Debug.WriteLine(BigInt.ToString()); 

而最好的關鍵可能不是一個Int64。我所擁有的是兩個Int32一起構成一個關鍵。和一個字節的值。我需要快速查找該組合鍵。字典很快,但它不支持組合鍵,所以我創建了一個實際上是組合鍵的單個鍵。在SQL Int32A中,Int32B構成PK。

我不使用複合鍵的原因是我想查找字典的速度和我的知識字典不支持複合鍵。這是生產代碼。在SQL表中實際上有第三個鍵(Int32 sID,Int32 IntA,Int32 IntB)。在這個解析器中,我一次只處理一個sID(並且按照順序處理sID)。我開始用SQL查詢組合鍵(一次運行數十億次)。當我將IntA,IntB輸出到Dictionary來處理單個sID時,在完成每個sID時加載到SQL,我得到了100:1的性能提升。性能改進的一部分是插入,因爲當我從字典中插入時,我可以按PK順序插入。新的IntA和IntB不會按照解析進行排序,因此直接插入SQL會嚴重地破壞索引,我需要在運行結束時重建索引。

+1

「直數學」是什麼意思?請顯示一些代碼來說明兩個int32和int64之間的關係。 – 2012-04-01 17:43:27

+0

@OliCharlesworth我添加了一個我使用的直數學的簡單樣本。 – Paparazzi 2012-04-01 17:59:05

+0

'Int32.MaxValue'是2^32-1。你確定這就是你想要的嗎? – 2012-04-01 18:00:26

回答

7

聽起來像你只是想換班。我個人覺得它簡單,使用無符號類型時,想想bitshifting代替簽字的國家:

// Note: if you're in a checked context by default, you'll want to make this 
// explicitly unchecked 
uint u1 = (uint) int1; 
uint u2 = (uint) int2; 

ulong unsignedKey = (((ulong) u1) << 32) | u2; 
long key = (long) unsignedKey; 

,並扭轉:

ulong unsignedKey = (long) key; 
uint lowBits = (uint) (unsignedKey & 0xffffffffUL); 
uint highBits = (uint) (unsignedKey >> 32); 
int i1 = (int) highBits; 
int i2 = (int) lowBits; 

這是完全可能的,你並不需要所有這些轉換爲unsigned類型。這比什麼都重要:)

請注意,您需要轉換u1ulong以便在正確的空間轉移作品多爲我的理智 - 移位uint由32位會做什麼。

請注意,這是a組合兩個32位整數得到64位整數的方法。這不是只有方式。

(邊注:巴斯的解決方案可以工作得很好 - 我只是一直用那種方式有點不舒服,因爲沒有具體的原因。)

+0

僅供參考,OP的更新問題包含的代碼暗示它不僅僅是簡單的比特... – 2012-04-01 18:08:37

+0

@OliCharlesworth:我懷疑這更像是「這看起來可能會起作用」的人工產物,而不是一個蓄意的決定。已添加評論,但檢查。 – 2012-04-01 18:14:14

+0

@OliCharlesworth那數學就是我今天使用的。我只是想讓它更快。將查詢從SQL移動到Dictionary是一項巨大的性能改進,並希望優化Dictionary或者是否有更好的方法。 – Paparazzi 2012-04-01 18:42:18

11

如果你要來回的Int32的轉換的Int64的你可以使用一個顯式佈局的結構:

//using System.Runtime.InteropServices; 
[StructLayout(LayoutKind.Explicit)] 
struct Int64ToInt32 
{ 
    [FieldOffset(0)] 
    public Int64 Int64Value; 
    [FieldOffset(0)] 
    public Int32 LeftInt32; 
    [FieldOffset(4)] 
    public Int32 RightInt32; 
} 

只需設置/從字段中獲取值。

+1

請注意,爲了語言的互操作性,.NET命名約定會推薦'LeftInt32','RightInt32','Int64Value'和'Int64ToInt32'作爲名字。 – 2012-04-01 17:50:38

+0

僅供參考,OP的更新問題包含的代碼意味着它不僅僅是簡單的比特... – 2012-04-01 18:08:11

+0

哦!這很漂亮!它只是讓我開心。謝謝! – 2013-07-05 23:04:09

1

您可以使用位移將兩個32位值存儲在一個64位變量中。

我舉個小例子:

int a = 10; 
int b = 5; 
long c; 

//To pack the two values in one variable 
c = (long)a << 32; 
c = c + (long)b; 
//the 32 most significant bits now contain a, the 32 least significant bits contain b 

//To retrieve the two values: 
c >> 32 == a 
c - ((c>>32)<<32) == b 

編輯:我看到我有點遲到了,只是想在VS檢查,如果我沒有犯錯:)