Возможно, мой профилировщик (Netbeans) ввел меня в заблуждение, но я наблюдаю какое-то странное поведение, надеясь, что кто-то здесь может помочь мне понять это.
Я работаю над приложением, которое интенсивно использует довольно большие хеш-таблицы (ключи длинные, значения - объекты). Производительность встроенной java-хеш-таблицы (в частности, HashMap) была очень низкой, и, попробовав некоторые альтернативы — Trove, Fastutils, Colt, Carrot — я начал работать самостоятельно.
Код очень простой, использующий стратегию двойного хеширования. Это работает отлично и хорошо и показывает лучшую производительность из всех других вариантов, которые я пробовал до сих пор.
Загвоздка в том, что, согласно профайлеру, поиск в хэш-таблице является самым затратным методом во всем приложении, несмотря на то, что другие методы вызываются много раз и/или выполняют < em>намного больше логики.
Что меня действительно смущает, так это то, что поиск вызывается только одним классом; вызывающий метод выполняет поиск и обрабатывает результаты. Оба вызываются почти одинаковое количество раз, и метод, который вызывает поиск, имеет много логики для обработки результата поиска, но примерно в 100 раз быстрее.
Ниже приведен код для поиска хеша. По сути, это всего лишь два обращения к массиву (функции, вычисляющие хеш-коды, согласно профилированию, практически бесплатны). Я не понимаю, как этот кусок кода может быть таким медленным, поскольку это просто доступ к массиву, и я не вижу никакого способа сделать его быстрее.
Обратите внимание, что код просто возвращает ведро, соответствующее ключу, ожидается, что вызывающий объект обработает ведро. 'size' - это hash.length/2, hash1 выполняет поиск в первой половине хеш-таблицы, hash2 выполняет поиск во второй половине. key_index — это конечное целое поле в хэш-таблице, переданное в конструктор, а массив значений в объектах Entry представляет собой небольшой массив длинных значений, обычно длиной 10 или меньше.
Любые мысли людей по этому поводу очень ценятся.
Спасибо.
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;
}
Изменить, код для hash1 и 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)));
}
hash1
иhash2
. - person Qwerky   schedule 05.11.2010