2012-04-01 206 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检查,如果我没有犯错:)