在Kademlia protocol节点中,ID是160位数。节点存储在桶中,存储桶0存储与该节点具有相同ID的所有节点,除了最后一位,存储桶1存储除了最后2位之外与该节点具有相同ID的所有节点,因此所有160个桶。
找到应该将新节点放入哪个存储桶的最快方法是什么?
我的存储桶只是存储在一个数组中,需要一个像这样的方法:
Bucket[] buckets; //array with 160 items
public Bucket GetBucket(Int160 myId, Int160 otherId)
{
//some stuff goes here
}
显而易见的方法是从最重要的位开始,逐位比较,直到找到差异,我希望有一个更好的方法,基于聪明的位twiddling。
实用说明: 我的Int160存储在一个包含20个项目的字节数组中,优先使用这种结构的解决方案。
答案 0 :(得分:3)
您是否愿意考虑5个32位整数的数组? (或3个64位整数)?使用整个单词可能比使用字节提供更好的性能,但该方法应该适用于任何情况。
对两个节点ID的相应字进行异或,从最重要的开始。如果XOR结果为零,则转到下一个最重要的单词。
否则,使用constant time method from Hacker's Delight.找到此XOR结果中设置的最高有效位。如果设置了最高有效位,则该算法产生32(64),如果设置最低有效位,则该算法产生1,依此类推。该索引与当前单词的索引相结合,将告诉您哪个位不同。
答案 1 :(得分:2)
对于初学者,您可以逐字节(或逐字逐句)进行比较,并且当您在该字节(或字)内找到差异搜索时,可以获得第一个差异。
对我来说似乎有点难以理解的是,在一个桶阵列中添加一个节点会如此之快,以至于你是否做了一个聪明的比特来找到一个字节(或单词)中的第一个差异,或者只是流失在一个循环到CHAR_BIT(或其他东西)。但是可能。
此外,如果ID基本上是随机的,均匀分布,那么您会发现前8位的差异大约为255/256。如果您关心的只是平均情况行为,而不是最坏情况,那么就做一些愚蠢的事情:您的循环不太可能长时间运行。
作为参考,数字x
和y
之间的第一位差异是x ^ y
中设置的第一位。如果您使用GNU C编程,__builtin_clz
可能是您的朋友。或者可能__builtin_ctz
,我有点困......
你的代码看起来像Java,所以我想你正在寻找的bitfoo是integer log。