- PVSM.RU - https://www.pvsm.ru -
В процессе работы над хеш-таблицей возник обычный вопрос: какую из известных хеш-функций использовать. Образцов таких функций в сети множество, есть и «любимчики», использовавшиеся ранее и показавшие неплохой результат, в основном оценивавшийся «на глаз» — длины цепочек в хеш-таблице на боевых данных «примерно равны», значит, все работает так, как нужно; отдельные выбросы… ну что ж, ну выбросы, бывает.
В этот раз, наткнувшись на статью [1] и воодушевившись ею, решил получить более или менее объективную сравнительную оценку хеш-функций. Для этого были сформулированы требования к ним, в число которых вошли следующие:
В качестве тестовых данных я воспользовался тремя словарями из вышеупомянутой статьи, автору которой весьма признателен за сэкономленное время. Словари были преобразованы в windows-1251 и слиты в один файл. Всего получилось 327049 различных слов.
Первой жертвой экспериментов пала любимица с магической цифрой 37, ранее бездумно применявшаяся для хеширования всего и вся:
unsigned int HashH37(const char * str)
{
unsigned int hash = 2139062143;
for(; *str; str++)
hash = 37 * hash + *str;
return hash;
}
Одного взгляда на гистограмму было достаточно, чтобы понять, что выбросы, конечно, бывают, да, бывают… но не такие же
[2]
Впрочем, младшие два байта результата вполне юзабельны
[3]
[4]
а вот старшие как раз и дают то, что доводит общую картину до категории «печальная»
[5]
[6]
Итак, по «любимице» вывод: там, где достаточно 16 бит результата, функция вполне пригодна, в качестве же полного 32-битного хеша не годится абсолютно.
Естественно, после увиденного привычной хеш-функции пришлось подыскивать замену. Не мудрствуя лукаво, просмотрел все функции, подходящие по первому пункту (т.е. не требующие знания длины строки перед вычислением хеша), в статье [7], хеш-функциям и посвященной.
В число кандидатов попали (названия сохраняю оригинальные)
Из перечисленных только функции FAQ6, Rot13, Ly и Rs показали удовлетворительные результаты. Для остальных без лишних слов приведу распределения полного 32-битного значения:
Для признанных «подходящими» функций приведу полный код (немного измененный по сравнению с данным в статье-источнике, изменения в основном связаны с требованием отстутствия явно заданной длины хешируемой строки) и распределения как полного 32-битного значения, так и каждого байта.
unsigned int HashFAQ6(const char * str)
{
unsigned int hash = 0;
for (; *str; str++)
{
hash += (unsigned char)(*str);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
return hash;
}
32-битное значение
[15]
первый байт
[16]
второй байт
[17]
третий байт
[18]
четвертый байт
[19]
unsigned int HashRot13(const char * str)
{
unsigned int hash = 0;
for(; *str; str++)
{
hash += (unsigned char)(*str);
hash -= (hash << 13) | (hash >> 19);
}
return hash;
}
32-битное значение
[20]
первый байт
[21]
второй байт
[22]
третий байт
[23]
четвертый байт
[24]
unsigned int HashLy(const char * str)
{
unsigned int hash = 0;
for(; *str; str++)
hash = (hash * 1664525) + (unsigned char)(*str) + 1013904223;
return hash;
}
32-битное значение
[25]
первый байт
[26]
второй байт
[27]
третий байт
[28]
четвертый байт
[29]
unsigned int HashRs(const char * str)
{
static const unsigned int b = 378551;
unsigned int a = 63689;
unsigned int hash = 0;
for(; *str; str++)
{
hash = hash * a + (unsigned char)(*str);
a *= b;
}
return hash;
}
32-битное значение
[30]
первый байт
[31]
второй байт
[32]
третий байт
[33]
четвертый байт
[34]
Из всех протестированных функций наибольшую скорость работы продемонстрировала DJB. Несмотря на то, что в число «годных» функций она не попала, затраченное ею время на обработку всех тестовых слов я принял за 100% и соотнес с ним время работы остальных функций. Получилось следующее:
DJB | 100 |
SDBM | 111 |
BKDR | 113 |
H37 | 113 |
Ly | 122 |
Js | 125 |
Rs | 125 |
Rot13 | 145 |
AP | 159 |
ELF | 184 |
PJW | 191 |
FAQ6 | 205 |
Если оставить в таблице только выбранные для использования функции, получим
Ly | 122 |
Rs | 125 |
Rot13 | 145 |
FAQ6 | 205 |
Рассмотрев статистические характеристики некоторых известных хеш-функций, мы выбрали из них те, что показали наиболее равномерное распределение как по полному 32-битному значению, так и по отдельным байтам и захабрили (для истории?) их исходный код. Следует отметить, что не вошедшие в четверку «лидеров» функции могут оказаться предпочтительными при других условиях, например, если полученное значение берется по какому-либо модулю. Мы такие случаи не рассматривали.
Благодарю за внимание.
Автор: madcomaker
Источник [35]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/58836
Ссылки в тексте:
[1] статью: http://vak.ru/doku.php/proj/hash/efficiency
[2] Image: http://postimg.org/image/8ye4jc8sj/
[3] Image: http://postimg.org/image/8stdcsrvz/
[4] Image: http://postimg.org/image/5d9wci4h1/
[5] Image: http://postimg.org/image/c66uux6np/
[6] Image: http://postimg.org/image/6prlee1wl/
[7] статье: http://vak.ru/doku.php/proj/hash/sources
[8] Image: http://postimg.org/image/68ethi5ut/
[9] Image: http://postimg.org/image/736yje4k9/
[10] Image: http://postimg.org/image/8m596kh9f/
[11] Image: http://postimg.org/image/ym8g0ecap/
[12] Image: http://postimg.org/image/geom0dr05/
[13] Image: http://postimg.org/image/q1tyfhd8n/
[14] Image: http://postimg.org/image/4y0vky8e1/
[15] Image: http://postimg.org/image/s95jpb1g7/
[16] Image: http://postimg.org/image/n9kv95xp1/
[17] Image: http://postimg.org/image/v7jvok0d1/
[18] Image: http://postimg.org/image/qnwh7alwx/
[19] Image: http://postimg.org/image/g0ym6wbkp/
[20] Image: http://postimg.org/image/5314txr4p/
[21] Image: http://postimg.org/image/8lpv5muyz/
[22] Image: http://postimg.org/image/avhxolixj/
[23] Image: http://postimg.org/image/4xss60eun/
[24] Image: http://postimg.org/image/g24hba4m5/
[25] Image: http://postimg.org/image/snn9s0eh9/
[26] Image: http://postimg.org/image/c544cxgel/
[27] Image: http://postimg.org/image/3kuvnn02t/
[28] Image: http://postimg.org/image/8ze165d8b/
[29] Image: http://postimg.org/image/7pt8rr6yd/
[30] Image: http://postimg.org/image/71gjbvsn5/
[31] Image: http://postimg.org/image/kxzajo7l7/
[32] Image: http://postimg.org/image/s43ml8krd/
[33] Image: http://postimg.org/image/tn4ufxggp/
[34] Image: http://postimg.org/image/zbwqt903l/
[35] Источник: http://habrahabr.ru/post/219139/
Нажмите здесь для печати.