My Netbeans profiler may be misleading, but I see some strange behavior, hoping someone can help me figure this out.
I am working on an application that heavily uses fairly large hash tables (keys are long, values ββare objects). Performance with the built-in java hash table (HashMap specifically) was very poor, and after trying some alternatives - Trove, Fastutils, Colt, Carrot - I started working on my own.
The code is very simple using a double hash strategy. This works well and shows the best performance of all the other parameters that I have tried so far.
The trick, according to the profiler, hash table search is the most expensive method in the entire application - despite the fact that other methods are called many times and / or do a lot more logic.
What really bothers me is the search with only one class; the calling method performs a search and processes the results. Both are called almost the same number of times, and the method that calls the search has a lot of logic in it to process the search result, but about 100 times faster.
Below is the hash search code. These are basically just two calls to the array (functions that calculate hash codes, according to profiling, are actually free). I donβt understand how this bit of code can be so slow, because it is just accessing the array, and I donβt see any way to speed up its execution.
Note that the code simply returns the bucket corresponding to the key, as expected, the handler will process the bucket. 'size' - hash.length / 2, hash1 searches in the first half of the hash table, hash2 searches in the second half. key_index is the final int field in the hash table passed to the constructor, and the array of values ββin Entry objects is a small array of lengths, usually 10 or less.
Any thoughts that people have on this are greatly appreciated.
Thank.
public final Entry get(final long theKey) {
Entry aEntry = hash[hash1(theKey, size)];
if (aEntry != null && aEntry.values[key_index] != theKey) {
aEntry = hash[hash2(theKey, size)];
if (aEntry != null && aEntry.values[key_index] != theKey) {
return null;
}
}
return aEntry;
}
Change, code for hash1 and hash2
private static int hash1(final long key, final int hashTableSize) {
return (int)(key&(hashTableSize-1));
}
private static int hash2(final long key, final int hashTableSize) {
return (int)(hashTableSize+((key^(key>>3))&(hashTableSize-1)));
}