9 ms·
Interactive Demo of Bloom Filters
- natch 9y agoYou don't need more than one hash function. Just append an incrementing token onto the input before each successive hash.
- chrisseaton 9y ago> Just append an incrementing token onto the input before each successive hash. But that's a new hash function then.
- natch 9y agoObviously not. It's a new input into the same hash function.
- ThePhysicist 9y agoIf you're interested in using Bloom filters in the backend, we (at DCSO) have written efficient and interoperable open-source implementations in Python and Go, also using FNV-1 hashing: https://github.com/DCSO/bloom https://github.com/DCSO/bloom (Go version) https://github.com/DCSO/flor https://github.com/DCSO/flor (Python version) The Go version comes with a command line tool that allows you to use Bloom filters on the shell.
- bane 9y agoOne note: if you've done everything correctly under the hood, instead of reading and writing the entire filter into and out of memory, just mmap the file and operate on it directly. It turns out to be pretty fast, especially on SSDs and you can make both many filters and test them quickly this way, or make filters that are practically larger than RAM and swap partitions and make absolutely enormous sets.
- ThePhysicist 9y agoYes good point, we actually have this on the roadmap!
- imajes 9y agohey, curious why your variables in the go version are so terse? makes following along a little tough!
- fooker 9y agoIt is Go 'style'. The abstractions are supposed to be self explanatory and simple and thus the variable names do not have to serve as documentation.
- jerf 9y agoI think it is Go style to name things that come in as interfaces with short names. When you have an io.Writer, there's very little else you can name it other than "w" that would have any additional meaning or utility. When you have a variable or struct field of a concrete type, it can and should have a meaningful name, even in Go. Ironically, I see several "input io.Reader" sort of things in that code, where as "number of hash functions" is k. A few minutes with go-rename would clean that right up, though. Go to https://golang.org/pkg/net/http/#Client https://golang.org/pkg/net/http/#Client and use your browser to search for the string "struct {" and have a look. https://golang.org/pkg/os/ https://golang.org/pkg/os/ is another page with a number of struct declarations.
- netcraft 9y agoobligatory mention that if you are interested in this you should also know about cuckoo filters: https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf https://en.wikipedia.org/wiki/Cuckoo_hashing https://en.wikipedia.org/wiki/Cuckoo_hashing
- avmich 9y agoI also found this - https://bdupras.github.io/filter-tutorial/ https://bdupras.github.io/filter-tutorial/ - interesting.
- kristoff_it 9y ago...and a shameless plug for my (WIP) Redis Module that doesn't implement a "bloomy" interface, for once https://github.com/kristoff-it/redis-cuckoofilter https://github.com/kristoff-it/redis-cuckoofilter
- GordonS 9y agoDo you have a tldr for how/when it is better than bloom filters?
- kappaloris 9y agoWhen you want an error rate lower than 3% and you can properly size the filter as it can fail insertions if you overfill it.
- hendler 9y agoThe OP also posted http://www.lkozma.net/cuckoo_hashing_visualization/ http://www.lkozma.net/cuckoo_hashing_visualization/
- spike021 9y agoCuckoo hashing was one of the more interesting concepts I learned back in school. Definitely a fun way of implementing a hash table.
- geocar 9y agoIf anyone just wanted to see a collision: a 2 c collides with: f
- bearded_comrade 9y agoAnother one is 1111 collides with ab
- taco_emoji 9y agoAnother anomaly is that "hello" yields the same array position for all three hashes, which makes it highly prone to collision.
- geocar 9y agoSame with: The Answer to The Ultimate Question of Life, The Universe, and Everything. which means that if FORTY-TWO. has been inserted, you'll find that as a possible answer.
- jauntbox 9y agoEven better, just e and f collide.
- callahad 9y ago> Unfortunately I can't use the 64-bit trick in the linked post as JavaScript only supports bitwise operations on 32 bits. This could be a good use case for WebAssembly, which supports 64-bit math natively.
- cr0sh 9y agoAm I understanding this correctly? 1) For each key, you generate a "hash" - which is a bit position 2) The hash generation is such to ensure that the bit location in the filter is probabilistically distributed for each key (so they are spread "evenly", for lack of a better term, over the length of the filter) 3) You generate so many locations per key, the number of which is the number of hash generators you are using (so if you have 3 generators, you get 3 distributed bit positions) 4) Some keys may cause overlaps/collisions - but this is ok 5) At some point, you fill up the filter with keys 6) To see if a key is -probably- in the filter, you run the same steps again and see if the bits are set; if they are, then it -probably- is 7) You then run that key on your regular index search; some false positives though will cause you to run that expensive operation and get back nothing, but usually you'll get back something (true positive). But if that key wasn't found in the filter, you definitely don't run the expensive lookup at all. Is that correct? There must also be something that the bit position "hash" generators have to be able to span an arbitrarily large bit range, in order to "store" more keys; this trivial example would look like it would fill up rather quickly (one all bits are set to "1", any key would generate a "positive" and you would always be running the expensive lookup - whether it was in the index or not - basically, falling back to a default state). If I have all of that correct (or close) - or even if I don't - it seems like a very powerful technique, limited to only that bit length (and being able to perform bitwise operations on it quickly), which (unless I am missing something?) would need to be fairly long to accommodate a reasonable number of keys (for say a record lookup in an rdb table). What might also be nice would be a way to detect it is "filled up" and bypass the test; you'd fall back to the worst case scenario (ie - no bloom filter), but at least you wouldn't be running the bloom filter check on top of that as well, incurring an extra demand. I'm thinking there's probably something easily done here - some bitwise operation that could be done (maybe take the inverse and compare it to zero?).
- tekromancr 9y agoPretty close. Except 1) you generate multiple hashes for a particular value, thus setting multiple bits for a value 5) when this happens, you use a larger filter 6) You can also determine with 100% confidence that a value isn't in the set. Other than that, I think you have a good idea of what it's about. Once I learned about this, I got tons of great ideas. Right now, I think it would be cool to construct a bloom filter for detected bot users on twitter. You could make a plugin that marked tweets from probable bot-users as such without storing the whole db on disk, and without making tons of network requests.
- thinkr42 9y agoThis is great, but think "Probably is in there" should be replaced with "Might be in there".
- tekromancr 9y agoFor this toy example, sure. But extend it from a 2byte table to, for example, a 50MB table and use many more hashes. The larger the table, and the more hash functions you use, the smaller the false positive error becomes. If you have a limited dataset that you want to test against, you can set these params to have a near 0% false positive rate, at the expense of a much larger table
- Assossa 9y agoIf you want a simple explanation of bloom filters: To add to filter: 1) Get multiple hashes of the data. You can use the same hash function and increment the data each hash, or use multiple hash functions. You can do any amount of hashes from 1 to infinity, each filter size and dataset size has a sweet spot. 2) Mod (remainder) each hash by the filter size. The filter size can be any size, 1 to the maximum hash from your function[s]. The larger the filter, the more accurate the results, but a filter larger than your dataset is obviously useless. 3) Set each bit at the locations (from step 2) in the filter to 1. To check filter: 1) Do steps 1 & 2 from previous procedure. 2) Check each location in the filter. If all locations are 1, the data might be in the filter. If any of the locations are 0, the data is definitely not in the filter.
- taco_emoji 9y ago> a filter larger than your dataset is obviously useless This isn't obvious to me, can you explain?
- biggerfisch 9y agoAt that point, it's harder to search/test than just looking at your dataset, so there's no point to making the size that large
- irl_zebra 9y agoWell,the bloom filter only uses a tiny bit of space per data element and doesn't actually store the data. When searching the data itself, you're often searching through the actual data, which is more intensive and slow.
- avaer 9y agoI think CS education would be improved if these concepts didn't have mysterious names. Respect to Bloom, but the programming median might be raised if Bloom filters were called something stupid obvious like Hash Array Filler-upper Tables. We might not even need to spend time making visualizations to explain them.
- taeric 9y agoLast time this came up, I gave my wish that these had been called something like a Concierge filter. The metaphor being that you can ask the concierge of a hotel several questions about people that have been seen entering to get an idea if a given person is probably there.
- SyneRyder 9y agoWhile I'm not sure I agree about mysterious names, I do get confused whenever Bloom filters are mentioned on HN. I always think they're about bloom filters as applied to computer graphics: https://en.wikipedia.org/wiki/Bloom_(shader_effect) https://en.wikipedia.org/wiki/Bloom_(shader_effect)
- mikehollinger 9y agoThat'll just get renamed to a HAF table, which'll then get confused with some (to be invented) "half" table. ;-)
- middleorigin 9y agoI have no idea why you think the name helps remove the need for a visualization. Besides I think "filter" is more apt than "table"—it doesn't store anything per se.
- avaer 9y agoI never needed a picture to understand a hash table once I knew what a hash function was. If it were called a McCready table, that's one more trip to Wikipedia, plus one more every time I forget. Re: naming: It's a table of hash function results. It probabilistically stores a set. I don't see any filter here, though one use of the technique is indeed in filtering a list, though there are plenty more.
- in9 9y agoWhat is the efficiency of this algorithm? Is this how one can check for used usernames when a user is creating an account?
- joeblau 9y agoThey are also helpful in terms of space savings. I worked at a startup in Palo Alto in 2011 where we used a 100 GB in memory (Redis) Bloom Filter to de-duplcate links coming in from a real-time social media stream (Facebook, Twitter, Forums, etc..). While Bloom Filter does introduce false positives (collisions) we were willing to take the bet on that rather than allowing duplicate social media posts in our pipeline. If we wanted to store this information in a regular hash table, we would require a lot more space than the 1 bit per entry of a Bloom Filter.
- SatvikBeri 9y agoWouldn't a database lookup (with an index) be fast enough in that case? IIRC that's what Reddit does.
- in9 9y agoI have read about what reddit does, but idk if it was a simple (or hashed) database lookup or maybe a BF.
- greenpizza13 9y agoPresumably you have indexed based on username or the hash of a username, so the lookup is very inexpensive.
- taeric 9y agoYou could also send the bloom filter down to the client to filter out client side with high probability.
- deleted 9y ago[deleted]
- 9y ago