Какой алгоритм хеширования лучше всего подходит для уникальности и скорости? Примеры (хороших) применений включают хеш-словари.
Я знаю, что есть такие вещи, как SHA-256 и тому подобное, но эти алгоритмы предназначены для обеспечения безопасности , что обычно означает, что они медленнее, чем алгоритмы, которые менее уникальны . Я хочу, чтобы алгоритм хеширования был быстрым, но оставался достаточно уникальным, чтобы избежать коллизий.
algorithms
hashing
Earlz
источник
источник
Ответы:
Я протестировал несколько разных алгоритмов, измеряя скорость и количество столкновений.
Я использовал три разных набора ключей:
"1"
к"216553"
(вспомните почтовые индексы, и как плохой хэш сломал msn.com )Для каждого корпуса было зафиксировано количество столкновений и среднее время, проведенное за хешированием.
Я проверял:
xor
а не+
)Результаты
Каждый результат содержит среднее время хеширования и количество столкновений.
Примечания :
Действительно ли случаются столкновения?
Да. Я начал писать свою тестовую программу, чтобы увидеть, действительно ли случаются коллизии хешей - и это не просто теоретическая конструкция. Они действительно случаются
Столкновения ФНВ-1
creamwove
сталкивается сquists
Столкновения ФНВ-1а
costarring
сталкивается сliquid
declinate
сталкивается сmacallums
altarage
сталкивается сzinke
altarages
сталкивается сzinkes
Murmur2 столкновения
cataract
сталкивается сperiti
roquette
сталкивается сskivie
shawl
сталкивается сstormbound
dowlases
сталкивается сtramontane
cricketings
сталкивается сtwanger
longans
сталкивается сwhigs
DJB2 столкновения
hetairas
сталкивается сmentioner
heliotropes
сталкивается сneurospora
depravement
сталкивается сserafins
stylist
сталкивается сsubgenera
joyful
сталкивается сsynaphea
redescribed
сталкивается сurites
dram
сталкивается сvivency
DJB2a столкновения
haggadot
сталкивается сloathsomenesses
adorablenesses
сталкивается сrentability
playwright
сталкивается сsnush
playwrighting
сталкивается сsnushing
treponematoses
сталкивается сwaterbeds
CRC32 столкновения
codding
сталкивается сgnu
exhibiters
сталкивается сschlager
SuperFastHash столкновения
dahabiah
сталкивается сdrapability
encharm
сталкивается сenclave
grahams
сталкивается сgramary
night
сталкивается сvigil
nights
сталкивается сvigils
finks
сталкивается сvinic
Randomnessification
Другая субъективная мера - насколько случайным образом распределены хэши. Отображение полученных HashTables показывает, насколько равномерно распределяются данные. Все хеш-функции показывают хорошее распределение при линейном отображении таблицы:
Или как карта Гильберта ( XKCD всегда актуален ):
Кроме случаев , когда хэширования число строк (
"1"
,"2"
, ...,"216553"
) (например, почтовые индексы ), где модели начинают появляться в большинстве алгоритмов хэширования:SDBM :
DJB2a :
FNV-1 :
Все, кроме FNV-1a , которые все еще выглядят довольно случайными для меня:
Фактически, Murmur2, кажется, имеет даже лучшую случайность с
Numbers
чемFNV-1a
:Дополнительное значение
*
в таблице обозначает, насколько плоха случайность. СFNV-1a
является лучшим, иDJB2x
является худшим:Первоначально я написал эту программу, чтобы решить, нужно ли мне беспокоиться о столкновениях.
И тогда это превратилось в то, что хэш-функции были достаточно случайными.
Алгоритм FNV-1a
Хэш FNV1 поставляется в вариантах, которые возвращают 32, 64, 128, 256, 512 и 1024-битные хэши.
Алгоритм FNV-1a является:
Где константы
FNV_offset_basis
иFNV_prime
зависят от размера возвращаемого хеша:Смотрите главную страницу FNV для деталей.
Все мои результаты с 32-битным вариантом.
FNV-1 лучше, чем FNV-1a?
FNV-1a лучше вокруг. Было больше столкновений с FNV-1a при использовании английского слова corpus:
Теперь сравните строчные и прописные буквы:
В этом случае FNV-1a не «на 400%» хуже, чем FN-1, только на 20% хуже.
Я думаю, что более важным выводом является то, что существует два класса алгоритмов, когда речь идет о столкновениях:
И затем, насколько равномерно распределены хэши:
Обновить
Ропщите? Конечно почему нет
Обновить
@whatshisname задалась вопросом, как будет работать CRC32 , добавила числа в таблицу.
CRC32 довольно хорош . Мало коллизий, но медленнее, и накладные расходы таблицы поиска 1k.
Отсеки все ошибочные материалы о распространении CRC - мой плохой
До сегодняшнего дня я собирался использовать FNV-1a в качестве своего фактического алгоритма хэширования хеш-таблицы. Но теперь я перехожу на Murmur2:
И я действительно, очень надеюсь, что что-то не так с
SuperFastHash
алгоритмом, который я нашел ; это слишком плохо, чтобы быть таким же популярным.Обновление: с домашней страницы MurmurHash3 в Google :
Так что, думаю, это не только я.
Обновление: я понял, почему
Murmur
быстрее, чем другие. MurmurHash2 работает с четырьмя байтами одновременно. Большинство алгоритмов побайтно :Это означает, что когда ключи становятся длиннее, Murmur получает шанс сиять.
Обновить
GUID разработаны для того, чтобы быть уникальными, а не случайными
Своевременное сообщение Рэймонда Чена подтверждает тот факт, что «случайные» GUID не предназначены для их случайности. Они или их часть не подходят в качестве хеш-ключа:
Randomess - это не то же самое, что избегать столкновений; вот почему было бы ошибкой пытаться изобрести свой собственный алгоритм «хэширования», взяв некоторое подмножество «случайного» guid:
Примечание : опять же, в кавычки я помещаю «случайный GUID» , потому что это «случайный» вариант GUID. Более точное описание будет
Type 4 UUID
. Но никто не знает, что типа 4 или 1, 3 и 5. Так что проще назвать их «случайными» GUID.Все английские слова зеркал
источник
Если вы хотите создать хеш-карту из неизменного словаря, вы можете рассмотреть возможность идеального хеширования https://en.wikipedia.org/wiki/Perfect_hash_function - во время создания хеш-функции и хеш-таблицы вы можете гарантировать: для данного набора данных, что не будет столкновений.
источник
Вот список хеш-функций, но короткая версия:
источник
CityHash от Google - это алгоритм, который вы ищете. Это не хорошо для криптографии, но хорошо для генерации уникальных хэшей.
Прочитайте блог для получения более подробной информации и код доступен здесь .
CityHash написан на C ++. Там также есть обычный порт C .
О 32-битной поддержке:
источник
plain C port
ссылка не работаетЯ составил краткое сравнение скорости различных алгоритмов хэширования при хэшировании файлов.
Отдельные графики лишь незначительно отличаются в методе чтения и могут быть проигнорированы здесь, так как все файлы были сохранены в tmpfs. Поэтому, если вам интересно, тест не был связан с IO.
Алгоритмы включают в себя:
SpookyHash, CityHash, Murmur3, MD5, SHA{1,256,512}
.Выводы:
CRC
инструкцией SSE 4.2s , которой нет у моего процессора. SpookyHash был в моем случае всегда чуть-чуть до CityHash.Источник, используемый для участков:
источник
Алгоритмы SHA (включая SHA-256) предназначены для быстрой работы .
На самом деле их скорость иногда может быть проблемой. В частности, распространенным методом хранения токена, полученного из пароля, является запуск стандартного алгоритма быстрого хеширования 10 000 раз (сохранение хэша хэша хэша пароля ...).
Выход:
источник
bcrypt
. Используйте правильные инструменты..rodata
и / или состояние. Когда вам нужен алгоритм для хеш-таблицы, у вас обычно есть очень короткие ключи и их много, но вам не нужны дополнительные гарантии криптографического ключа. Я сам использую измененный Дженкинс по отдельности.Предположение о том, что криптографические хеш-функции являются более уникальными, неверно, и на самом деле на практике может показаться, что оно часто имеет обратный характер. Поистине:
Это означает, что некриптографическая хеш-функция может иметь меньше коллизий, чем криптографическая, для «хорошего» набора данных - наборов данных, для которых она была разработана.
На самом деле мы можем продемонстрировать это с помощью данных в ответе Яна Бойда и немного математики: проблема дня рождения . Формула для ожидаемого числа сталкивающихся пар, если вы
n
случайным образом выбираете целые числа из набора[1, d]
: (взято из Википедии):При
n
подключении = 216,553 иd
= 2 ^ 32 мы получаем около 5,5 ожидаемых коллизий . Тесты Яна в основном показывают результаты в окрестностях, но с одним существенным исключением: большинство функций получили нулевые коллизии в последовательных числовых тестах. Вероятность случайного выбора 216 553 32-битных чисел и получения нулевых коллизий составляет около 0,43%. И это только для одной функции - здесь у нас есть пять различных семейств хэш-функций с нулевыми столкновениями!Итак, что мы видим здесь, так это то, что проверенные Яном хеши благоприятно взаимодействуют с последовательным набором чисел, т. Е. Они распределяют минимально разные входные данные более широко, чем идеальная криптографическая хеш-функция. (Примечание: это означает, что графическая оценка Яна, что FNV-1a и MurmurHash2 «выглядят случайными» для него в наборе данных номеров, может быть опровергнута из его собственных данных. Нулевые коллизии в наборе данных такого размера для обеих хеш-функций, поразительно неслучайно!)
Это не удивительно, потому что это желательное поведение для многих применений хеш-функций. Например, ключи хеш-таблицы часто очень похожи; В ответе Яна упоминается проблема, с которой MSN когда-то сталкивалась с хеш-таблицами почтового индекса . Это использование, когда предотвращение столкновений на вероятных входах выигрывает у случайного поведения.
Другое поучительное сравнение здесь - это контраст в целях разработки между CRC и криптографическими хеш-функциями:
Поэтому для CRC опять же хорошо иметь меньше коллизий, чем случайных, при минимально разных входах. С крипто хешами это нет-нет!
источник
Используйте SipHash . У него много желательных свойств:
Быстрый. Оптимизированная реализация занимает около 1 цикла на байт.
Secure. SipHash - это сильный PRF (псевдослучайная функция). Это означает, что он неотличим от случайной функции (если вы не знаете 128-битный секретный ключ). Следовательно:
Не нужно беспокоиться о том, что из-за коллизий ваши хэш-таблицы станут линейными по времени. С SipHash вы знаете, что вы получите среднюю производительность в среднем, независимо от входных данных.
Невосприимчивость к атакам типа «отказ в обслуживании» на основе хеш-функции.
Вы можете использовать SipHash (особенно версию с 128-битным выходом) в качестве MAC (Код аутентификации сообщения). Если вы получаете сообщение и тег SipHash, и этот тег совпадает с тегом запуска SipHash с вашим секретным ключом, то вы знаете, что тот, кто создал хеш, также владел вашим секретным ключом, и что ни сообщение, ни с тех пор хэш был изменен.
источник
Это зависит от данных, которые вы хэшируете. Некоторое хеширование лучше работает с конкретными данными, такими как текст. Некоторые алгоритмы хеширования были специально разработаны, чтобы быть подходящими для конкретных данных.
Пол Се однажды сделал быстрый хэш . Он перечисляет исходный код и объяснения. Но это уже было побито. :)
источник
Java использует этот простой алгоритм умножения и сложения:
Вероятно, есть намного лучшие, но это довольно широко распространено и кажется хорошим компромиссом между скоростью и уникальностью.
источник
Прежде всего, зачем вам нужно реализовывать собственное хеширование? Для большинства задач вы должны получить хорошие результаты со структурами данных из стандартной библиотеки, при условии, что есть доступная реализация (если вы просто делаете это для своего собственного образования).
Что касается реальных алгоритмов хеширования, то мой личный фаворит - FNV. 1
Вот пример реализации 32-битной версии на C:
источник
*
и^
:h = (h * 16777619) ^ p[i]
==>h = (h ^ p[i]) * 16777619