Live data from Hacker News

Trees, Hash Tables and Tries

benlynn.blogspot.com

21–24 of 24 posts

Re: Trees, Hash Tables and Tries

#21
post #14

In the real world, it's unlikely that a trie of any real size will be comparably performant to a hash table with a sane hash function: trie algorithms involve moving from node to node, each of which will require an unpredictable retrieval from non-sequential memory. Memory latency is pretty high these days (~200 cycles), so hash tables will almost always be quicker. This is not to say that radix tries aren't extremel…

what about judy-arrays[ http://judy.sourceforge.net/ ] ? they seem to be pretty seriously cache-optimized...

I've not encountered them before, but yes, they do seem to be very heavily optimised. I guess with relatively large nodes the quantity of cache misses is relatively low.

Re: Trees, Hash Tables and Tries

#22

Earlier quoted context omitted.

Bingo, string comparisons will eat you alive. Even if you have a very small percentage of collisions in your hash (even close to 0%), you still have to check if you have a collision to determine if you need to iterate to the next slot in the hash no matter what. If you are hashing strings, you have to compare the entire string, each character comparison is guaranteed to be at least one integer sub operation for 1 byt…

Fascinating - thanks for the detailed response, and that does make a lot of sense. It seems that if string comparisons are the major cost, you could speed up collision handling on the hash table quite a bit by storing additional metadata. Storing the size of the string, for example, would allow you to skip a lot of comparisons - you can do a simple size comparison prior to actually comparing characters. This would al…

No, not at all.

I think this is an incredible interesting, and often overlooked subject. I've even seen hashes that resolve collisions by sticking tries in the slots instead of linked lists for chaining. That way the "I'm checking for a collision" operation part of the hash becomes "give me the memory location 100% of the time I want". It essentially eliminates hash collisions in the classic sense, and the tries in the hash slots usually don't get very big/you can delay resizing the hash for quite a while (just use a different method like when the first trie hold more than n strings).

Some of the optimizations you mention make a lot of sense and I was generally responding with the more naive variations of the two concepts. One thing to keep in mind is that tries grow in memory amazingly fast. So fast that the rest of your system will have to start swapping out just to keep the trie in memory. A list of a quarter million tokens, average length of 6 will probably eat about 300-400MB before optimizations. If you restrict the tree depth to 4 or so, and stick hashes on the end, you can keep it around ~100MB. But a quarter million tokens is not really all that much, real life applications will usually involve millions of token. And a naive trie will rapidly outgrow the memory on 32-bit systems. It's the classic tradeoff, memory for speed. However, hashes are not really all that bad speed-wise. So the tradeoff isn't quite as good as one might hope. If you have to go to a trie from a hash to eek out an extra few percentage points in performance, you're likely having bigger problems.

In practice I've actually only used a trie a couple of times over a hash. Mostly because in the applications I'm using, I never have to grow the hash which is the most expensive hash operation. But also because there are already so many very good hash libraries in most languages particularly persistent hashes which can be very memory efficient. The practical different in speed between the two is really not that noticeable for most applications unless you are doing billions of lookups a day (in which case you probably are looking for a different setup anyway involving some kind of database).

Re: Trees, Hash Tables and Tries

#23

Earlier quoted context omitted.

Fascinating - thanks for the detailed response, and that does make a lot of sense. It seems that if string comparisons are the major cost, you could speed up collision handling on the hash table quite a bit by storing additional metadata. Storing the size of the string, for example, would allow you to skip a lot of comparisons - you can do a simple size comparison prior to actually comparing characters. This would al…

No, not at all. I think this is an incredible interesting, and often overlooked subject. I've even seen hashes that resolve collisions by sticking tries in the slots instead of linked lists for chaining. That way the "I'm checking for a collision" operation part of the hash becomes "give me the memory location 100% of the time I want". It essentially eliminates hash collisions in the classic sense, and the tries in t…

That is (again) really interesting/informative. Thanks - this is one of those conversations that really restores my faith in communicating over the web :-).

Re: Trees, Hash Tables and Tries

#24

Earlier quoted context omitted.

No, not at all. I think this is an incredible interesting, and often overlooked subject. I've even seen hashes that resolve collisions by sticking tries in the slots instead of linked lists for chaining. That way the "I'm checking for a collision" operation part of the hash becomes "give me the memory location 100% of the time I want". It essentially eliminates hash collisions in the classic sense, and the tries in t…

That is (again) really interesting/informative. Thanks - this is one of those conversations that really restores my faith in communicating over the web :-).

Actually, your idea of just sticking in the strlen on the hash nodes as a heuristic to prevent unnecessary collision checks is pretty good.

I too am glad to engage in this topic!

Post reply on HN