https://github.com/joeyrobert/bloomfilter使用Random类作为哈希函数performance killer 我要做的是用byte [] s而不是泛型参数(T)输入类并摆脱
private int Hash(T item) { return item.GetHashCode(); }
我知道有一个巨大的性能优势,但我不知道如何在这里替换_random.Next(_bitSize)
:
#region Public Methods
/// <summary>
/// Adds an item to the bloom filter.
/// </summary>
/// <param name="item">Item to be added</param>
public void Add(T item)
{
_random = new Random(Hash(item));
for (int i = 0; i < _numberOfHashes; i++)
_bitArray[_random.Next(_bitSize)] = true;
}
使用一些非延迟代码行,每个位不会占用数千个CPU周期。
我知道代码中还有很多其他问题可以使它更快/更安全。我(大多数时候)修复它们并且在推动我的更改之前卡在最后一个上。 任何帮助都非常感谢。
答案 0 :(得分:2)
我不明白你为什么要在这里使用随机数生成器...但是,我可以帮助你加快速度。
布隆过滤器基本上是一个位向量,您可以在其中设置位。如果你想弄清楚一个项目是否存在,如果项目可能存在,布隆过滤器会给你一个真假,如果项目肯定不存在则布隆过滤器 。
(我在一个简单的文本编辑器中执行此操作,因此代码中可能存在一些错误)
我假设你的哈希空间可以使用32位整数计算;如果你有一个非常大的bloom表,你可能想要使用64位整数。
布隆过滤器的最简单(也可能是最快)实现是:
byte[] bloomFilter = new byte[MyBloomFilterSize];
foreach (var item in myItems)
{
int hash = Hash(item) & 0x7FFFFFFF;
int bit = 1 << (hash & 7); // you have 8 bits
int index = (hash >> 3) % MyBloomFilterSize;
bloomFilter[hash % MyBloomFilterSize] |= bit;
}
您可以尝试将byte[]
更改为uint[]
或ulong[]
;我不确定这是否有所作为。
如果您想检查项目是否存在,则计算相同的索引和位,并获得结果。
public bool PossiblyExists(MyItem item)
{
int hash = Hash(item) & 0x7FFFFFFF;
int bit = 1 << (hash & 7); // you have 8 bits
int index = (hash >> 3) % MyBloomFilterSize;
return (bloomFilter[hash % MyBloomFilterSize] & bit) != 0;
}
这里唯一剩下的就是你可以计算哈希的速度。如果你使用的是整数,我只需将它乘以一个大的素数;如果你使用SHA256固定长度字节[](你似乎在做),你需要使它成为一个整数(或长整数)。
我在这里使用Buffer.BlockCopy来转换类型。为了安全起见,我更喜欢使用数据中的几个字节,但由于SHA256应该已经是随机的,因此一个简单的BitConverter.ToInt32(data, [0..28])
也可以做到这一点。
public int CalculateHash(byte[] data)
{
// Data = >128 bits = >16 bytes -- which is the same as >4 integers
int[] tmp = new int[4];
Buffer.BlockCopy(data, 0, tmp, 0, data.Length);
return tmp[0] ^ tmp[1] ^ tmp[2] ^ tmp[3];
}
应该这样做。
答案 1 :(得分:1)
例如,以下是一种有效的实现。如果您具有返回64位的哈希函数,则最好使用此函数代替murmur3_64。警告:我没有对其进行测试。
void Add(string item) {
ulong hash = murmur3_64((ulong) item.GetHashCode());
uint a = (uint) (hash >> 32);
uint b = (uint) hash;
for (int i = 0; i < k; i++) {
_bitArray[reduce(a, _bitSize)] = true;
// "Less Hashing, Same Performance: Building a Better Bloom Filter"
a += b;
}
}
ulong murmur3_64(ulong x) {
x = (x ^ (x >> 33)) * 0xff51afd7ed558ccdL;
x = (x ^ (x >> 23)) * 0xc4ceb9fe1a85ec53L;
x = x ^ (x >> 33);
return x;
}
uint reduce(uint hash, uint n) {
// http://lemire.me/blog/2016/06/27/a-fast-alternative-to-the-modulo-reduction/
return (hash * n) >> 32;
}