====== Эффективность хэш-функций ====== (Есть вариант этой статьи [[hash:efficiency-en | на английском языке]]) В статье Arash Partow [[http://www.partow.net/programming/hashfunctions/ | "General Purpose Hash Function Algorithms"]] приведены восемь вариантов 32-битных хэш-функций: * rs --- простая хэш-функция из книги Роберта Седжвика [[http://www.ozon.ru/context/detail/id/1425749/ | 'Фундаментальные алгоритмы на C']] * js --- побитовая хэш-функция от Justin Sobel * pjw --- алгоритм, основанный на работе Peter J. Weinberger * bkdr --- хэш-функция из книги Брайана Кернигана и Денниса Ритчи [[http://www.ozon.ru/context/detail/id/2480925/ | 'Язык программирования C']] * sdbm --- специальный алгоритм, используемый в проекте SDBM * djb --- алгоритм, разработанный профессором Daniel J. Bernstein * dek --- алгоритм, предложенный Дональдом Кнутом в книге [[http://www.ozon.ru/context/detail/id/2527036/ | 'Искусство программирования']] * ap --- алгоритм, разработанный Arash Partow Еще пять вариантов: * faq6 --- номер 6 из [[http://burtleburtle.net/bob/hash/hashfaq.html | FAQ Боба Дженкинса]] * lookup3 --- автор [[http://burtleburtle.net/bob/hash/ | Боб Дженкинс]] * ly --- предложен [[http://leo.yuriev.ru/random | Леонидом Юрьевым]] (конгруэнтный генератор) * rot13 --- простой алгоритм с циклическим сдвигом, от Сергея Вакуленко * crc32 --- [[http://www.w3.org/TR/PNG-CRCAppendix.html | стандартная контрольная сумма]] с полиномом x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 Тексты на языке Си можно посмотреть [[sources | здесь]]. ===== Тест номер 1 ===== Для проверки эффективности хэш-функций были выбраны следующие тестовые данные: * {{usdict.gz | Американский словарь}} из проекта Ispell, 62075 слов. * {{rudict.gz | Русский словарь}} из проекта Ispell, 128900 слов. * {{symbols.gz | Список имен}}, извлеченный из всех библиотек на моем linux-компьютере (libc.a и прочие), 136073 слов. Общее количество после слияния --- **326797** уникальных слов. При идеально равномерном распределении 32-битного хэша для достижения 50%-ной вероятности коллизии требуется 77163 слова. Так что коллизии должны иметь место. Для каждого из слов тестового наборы было вычислено 32-битное значение хэш-функции и подсчитано количество коллизий. ^ Алгоритм ^ Коллизии ^ ^ rs | 9 | ^ js | 98 | ^ pjw | 1315 | ^ bkdr | 11 | ^ sdbm | 14 | ^ djb | 83 | ^ dek | 308 | ^ ap | 16 | ^ ly | 9 | ^ rot13 | 7 | ^ faq6 | 14 | ^ lookup3 | 9 | ^ crc32 | 13 | Список коллизий для rs, bkdr, sdbm, ap, ly, rot13, faq6, lookup3 и crc32 можно посмотреть [[conflicts | здесь]]. Наиболее эффективные функции: * [[sources#ROT13 Hash Function| rot13]] --- один циклический сдвиг и сложение * [[sources#LOOKUP3 Hash Function| lookup3]] --- один сдвиг и сложение (или больше) * [[sources#LY Hash Function| ly]] --- одно умножение и сложение * [[sources#RS Hash Function| rs]] --- два умножения Результаты представлены на графике. Два явных аутсайдера --- pjw и dek --- выходят за пределы графика. {{hash-eff.png}} ---- ===== Тест номер 2 ===== В предыдущем тесте данные имели общее свойство - неизменный старший бит каждого байта. Это могло повлиять на результат. Поэтому был проведен повторный тест, для которого были выбраны другие наборы данных: * {{dedict.gz | Немецкий словарь}} из проекта Ispell, 39612 слов. * {{hudict.gz | Венгерский словарь}} из проекта Ispell, 211880 слов. * {{itdict.gz | Итальянский словарь}} из проекта Ispell, 37268 слов. * {{sedict.gz | Шведский словарь}} из проекта Ispell, 24019 слов. Общее количество после слияния --- **310595** уникальных слов. В тесте не участвовали алгоритмы js, pjw, djb и dek. ^ Алгоритм ^ Коллизии ^ ^ rs | 5 | ^ bkdr | 14 | ^ sdbm | 14 | ^ ap | 32 | ^ ly | 8 | ^ rot13 | 10 | ^ faq6 | 13 | ^ lookup3 | 14 | ^ crc32 | 15 | Наиболее эффективные функции: * [[sources#RS Hash Function| rs]] --- два умножения * [[sources#LY Hash Function| ly]] --- одно умножение и сложение * [[sources#ROT13 Hash Function| rot13]] --- один циклический сдвиг и сложение Результаты представлены на графике. {{de-hu-se-it.png}}