【问题标题】:Bloom Filter hash is returning far too many collisions布隆过滤器哈希返回太多冲突
【发布时间】:2017-03-15 21:38:07
【问题描述】:

我一直在尝试实现我自己的(简单)布隆过滤器,但我坚持使用散列,我理解多次散列项目并使用索引填充位数组的概念。

但是,我在哈希中看到大量冲突,我正在使用 1 种哈希算法(我尝试过 FNV、murmurhash 和现在的farmhash)和各种种子(基于当前的纳秒)。

我一定是做错了什么,我是按照information here 计算k 函数并设置相同数量的种子。

任何帮助都会很棒,谢谢。

const farmhash = require('farmhash');

class BloomFilter {
	constructor(items, input)
	{
		const BITS_PER_ITEM = 15; //~0.1% false positive rate
		this.m = Buffer.alloc(items.length * BITS_PER_ITEM); // setup bit array
		this.k = Math.ceil(BITS_PER_ITEM * 0.7); // amount of hash functions we need to use
		this.seeds = [];
		this.input = input;
		this.items = items;

		this.setSeeds();
		this.insertItems();
	}

	get time()
	{
		let hrTime = process.hrtime()
		return hrTime[1];
	}

	setSeeds()
	{
		for(let i = 0; i <= this.k; i++) this.seeds.push(this.time);
	}
	
	insertItems()
	{
		console.log('Total buffer size: ' + this.m.length);

		let collisions = 0;
		this.items.forEach(value => {			
			this.getBufferIndices(value).map(index => {
				if(this.m[index] === 1) collisions++;
				this.m[index] = 1;
			});
		});

		console.log('Total collisions: ' + collisions);
	}

	getBufferIndices(value)
	{
		let indicies = [];

		this.seeds.forEach(seed => indicies.push(farmhash.hash32WithSeed(value, seed) % this.m.length));

		return indicies;
	}
}

module.exports = BloomFilter;

【问题讨论】:

  • 请在您的问题中发布代码,而不仅仅是当前版本的链接。
  • @Bergi 我的错,已修复

标签: javascript node.js algorithm ecmascript-6 bloom-filter


【解决方案1】:

根据我对 Bloom 过滤器的记忆,当 all k 特定值的索引与不同值的索引匹配时会发生冲突。

您似乎将一个 单个 存储桶 (this.m[index]) 之前已设置为冲突。

以下(未经测试的)代码应计算实际冲突:

let collisions = 0;

this.items.forEach(value => {           
  let overlap = 0;
  this.getBufferIndices(value).map(index => {
    if(this.m[index] === 1) overlap++;
    this.m[index] = 1;
  });
  if (overlap === this.k) collisions++;
});

正如@Thomas 在他的评论中正确指出的那样,您应该使用.forEach(),而不是使用.map()(创建一个新数组):

this.getBufferIndices(value).forEach(index, ...);

getBufferIndices() 中,您可以使用.map() 代替.forEach()

getBufferIndices(value) {
  return this.seeds.map(seed => (farmhash.hash32WithSeed(value, seed) % this.m.length));
}

【讨论】:

  • @Connor 请不要使用Array#map 来完成forEach 的工作,或者reduce。这会创建一个不必要的 Array,它只分配内存并且必须是 GC。你不在这里处理小数组。
  • @robertklep 当然,非常感谢 - 我认为是看代码太多了。
  • @Thomas 谢谢,重构后忘记改了
猜你喜欢
  • 2018-07-21
  • 1970-01-01
  • 2014-10-02
  • 2019-03-25
  • 2014-11-10
  • 2019-04-27
  • 2010-10-14
  • 2011-09-30
  • 2012-08-10
相关资源
最近更新 更多