Hash function performance
scripting.com
scripting.com
(On average they're going to need to compare with 6324 other objects before they've gotten the right one. A perfect hash function would end up 5686 checks. Willing to bet that the 639 fewer checks would make up for a better hash function.)
But that's just the beginning of the problem! I mean, even with a hash function that's that bad, ~100 buckets would get them nearly 10X better performance! And realistically, why not use several thousand buckets? Come on ...
* Learn more about the theory behind hashes before designing one.
* Use a hash that distributes evenly across buckets.
* Learn what random looks like.
If it was random, all the numbers would be chosen with close to the same probability. So there would be an even number of items in each bucket. What we have here shows that bucket 1 is rarely chosen and bucket 7 is really common. The spread is so ridiculous (17.6k vs. 3.8k) that it cannot be due to chance.
In short, this is an absurd hash function. Do not use it in cryptography or elsewhere. If you need simple, low-cost, non-cryptographic hashes, look here:
http://www.cs.hmc.edu/~geoff/classes/hmc.cs070.200101/homewo...
Using an appropriate number of buckets would actually reduce memory usage.
Using an appropriate hash function (one that at least considered all the characters in the key) wouldn't increase the time to hash a string read off a floppy disk, because he's using the first and last characters anyway.
Of course that will expose how bad the hash function really is. Saving a few cycles in the hash function and then chaining through 17k linked list entries doesn't make any sense.
But there's no denying how atrocious the hash function is. To quote:
> first and last characters of the name of the object, adds them together and mods the result by the number of buckets, which is 11
I don't know much about the name representation, but I'm guessing it's human readable ASCII. Which means your keys are confined to a very narrow range, and they'll be distributed along the same lines as the language itself (English or whatever). That means collisions up the wazoo.
It's main issue is that it turns large tables into an O(n/10) linked list. It was kinda painful for a few things 10 years ago, and it was a reasonable hack 10 years before that when it was likely originally written. Iirc, there was one pathological case where all the items ended up in one bucket, but that's lost to the sands of time.
Fwiw, md5 has been available in his system since 98 or so, and any security related stuff would have been using that.
This is a horrible hash function for a number of reasons. You want your hash function to use every bit of information from the data you're keying on because that's more likely to give you a spread that doesn't contain a collision. Consider this list of keys:
aaz abz axz
Those three keys would collide, and for no reason. Even adding up each letter (another horrible hash function because it eliminates information about the position of the character, so "the" and "eht" would collide) would be better than this.
Information theory is important here; you want to preserve as much information from your key as possible. Check out http://en.wikipedia.org/wiki/Entropy_(information_theory) for a good discussion on this.
Also, there is almost no earthly reason to use a hash function with 11 buckets, and you certainly wouldn't want to evaluate your hash based on that. Assuming you'd have to search each bucket of 10,000 for your match, hashing it into 11 sections buys you very little time.
Also, there's no reason not to do something more complicated; assuming your key is in CPU cache because you're going to add the first and last letters, why not at least add up all the letters? You're wasting free CPU cycles after you've already loaded the key from memory.
Finally, you don't want output that "looks pretty random." You want output that sorts exactly evenly between buckets. He's nowhere close.