Это правильное использование встроенной хэш-функции Python? - PullRequest
15 голосов
/ 04 октября 2011

Мне нужно сравнивать большие куски данных на равенство, и мне нужно сравнивать много в секунду, fast . Каждый объект гарантированно имеет одинаковый размер, и возможно / вероятно, что они могут быть лишь незначительно различными (в неизвестных позициях).

В интерактивном сеансе, показанном ниже, я видел, что использование оператора == для байтовых строк может быть медленнее, если различия находятся в конце строки, и может быть очень быстрым, если есть различия в начале.

Я подумал, что может быть какой-то способ ускорить процесс с использованием некоторого хэша, конечно, вычисление хеша md5 и сравнение довольно медленнее, но встроенный хэш python, похоже, значительно ускоряет процесс.

Тем не менее, я понятия не имею о деталях реализации этого хеша, действительно ли он похож на хеш, поскольку мне может быть удобно, что когда hash(a) == hash(b), то a == b очень вероятно? Я рад получить несколько неверных результатов, если коллизия хеша достаточно редка (редко в смысле необходимости массива из 200 PS3 за несколько часов для коллизии )

In [1]: import hashlib

In [2]: with open('/dev/urandom') as f:
   ...:     spam = f.read(2**20 - 1)
   ...:     

In [3]: spamA = spam + 'A'

In [4]: Aspam = 'A' + spam

In [5]: spamB = spam + 'B'

In [6]: timeit spamA == spamB
1000 loops, best of 3: 1.59 ms per loop

In [7]: timeit spamA == Aspam
10000000 loops, best of 3: 66.4 ns per loop

In [8]: timeit hashlib.md5(spamA) == hashlib.md5(spamB)
100 loops, best of 3: 4.42 ms per loop

In [9]: timeit hashlib.md5(spamA) == hashlib.md5(Aspam)
100 loops, best of 3: 4.39 ms per loop

In [10]: timeit hash(spamA) == hash(spamB)
10000000 loops, best of 3: 157 ns per loop

In [11]: timeit hash(spamA) == hash(Aspam)
10000000 loops, best of 3: 160 ns per loop

1 Ответ

29 голосов
/ 04 октября 2011

Хэш-функция Python разработана для скорости и отображается в 64-битном пространстве.Из-за парадокса дня рождения это означает, что вы, вероятно, столкнетесь с 5 миллиардами записей (вероятно, намного раньше, поскольку хеш-функция не является криптографической).Кроме того, точное определение hash зависит от реализации Python и может зависеть от архитектуры или даже конкретной машины.Не используйте его, вам нужен один и тот же результат на нескольких машинах.

md5 разработан как криптографическая хеш-функция;даже незначительные возмущения на входе полностью меняют выход.Он также отображается в 128-битном пространстве, что делает маловероятным, что вы когда-либо столкнетесь с коллизией, если только вы специально не ищете ее.

Если вы можете справиться со коллизиями (т. Е. Проверить на равенство между всемиэлементы в корзине (возможно, с использованием криптографического алгоритма, такого как MD5 или SHA2), хэш-функция Python прекрасно работает.

Еще одна вещь: чтобы сэкономить место, вы должны хранить данные в двоичном виде, если вы их напишитена диск.(т.е. struct.pack('!q', hash('abc')) / hashlib.md5('abc').digest()).

В качестве примечания: is не эквивалентно == в Python.Вы имеете в виду ==.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...