Benchmarking hash table implementations: C++, Java, LuaJIT
lonewolfer.wordpress.com
lonewolfer.wordpress.com
[Typical hash table accesses use a) string keys with b) a high temporal correlation and c) they usually have a high hit-rate or a high miss-rate, but it's rarely 50/50.]
Surely there is a simple, simple routine that does all this. I want to see this benchmark done right. If it's so simple, why hasn't anyone written it down? The author updated:
If have some extra time I'll test some variables later on I will test different hit rates and key types. If you have a reference to a source where statistics around hash table use cases is investigated I'll use that as a basis.
I recommend JMH which I believe is what was developed @ Oracle to handle this task.
I used it to microbenchmark various Java maps for small map sizes and showed some of the results. https://groups.google.com/forum/#!topic/mechanical-sympathy/...
I also found the discussion of various map implementation tradeoffs and caveats useful. That Google group is a great resource.
One thing you have to keep in mind when benchmarking maps is locality and cache affinity and how things will work outside the benchmark when things don't fit in cache or have been evicted by your application.
In my case map lookups showed up in profiles relating to various lookup tables that define logic and policy. There can be a surprising number spread out as well as some hit hard in tight loops.
From my admittedly limited knowledge a better benchmark would involve:
- String keys because who uses int keys? It would be important to create a new set of query keys for retrieving values that would contain a mix of newly created strings as well as older ones to account for any hashcode memoization. - Non-primitive values. This would address the boxing overhead someone mentioned and would be much closer to real life usage. - Many more runs. Since there are performance implications of data access patterns due to spatial locality using a larger number of runs this would help even those out.
Another question is, why? The ultimate choice of Java vs C++ won't depend on how fast the standard hash tables are.
Good discussion too. khash.h uses macros for C templating, but is quite fast.
As another comment suggests, large maps are likely to be accessed concurrently, and so a comparison of concurrent hash maps would also be interesting.
> A return value of null does not necessarily indicate that the map contains no mapping for the key; it's also possible that the map explicitly maps the key to null. The containsKey operation may be used to distinguish these two cases.
http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.h...
eg, http://trove.starlight-systems.com/ or http://acs.lbl.gov/software/colt/ in the case of the Java version.
EDIT: Here is the kind of performance differences you get between hash implementations to demonstrate why you wouldn't just use the standard implementations if it's a performance critical part: http://b010.blogspot.com/2009/05/speed-comparison-of-1-javas...
Shows Colt int map running 3.5x faster and with 65% of the ram usage as the standard hashmap.
If there's a better general-purpose hash table, the standard library hash should be using it.
(Special-purpose, sure, use a custom data structure.)
The standard library doesn't contain these, because in 99% of apps, the actual performance of the hash table is a very minor part and a small bit of overhead for added convenience is worth it. However in a program where the hashmap is the key point, you'd obviously choose to optimize it to fit your goals.
If your application is even 80% giant hash table lookup, I would presume it is doing so in a fairly highly multithreaded environment. Caching systems, maybe?
Otherwise, I would think the times where this benchmark matters are few and far between. If you find you are looking up a ton of items in a hash table in such a way that that shows up in a profile, you are probably best off moving to a sorted list and just iterating through the items as you need. Right?