Подтвердить что ты не робот

Согласованный хеш строки String, основанный только на строчном контенте

ЦЕЛЬ: Сопоставлять каждый URL, обрабатываемый сервером, до 0, 1, 2 или 3, распределяя как можно более равномерно.

В то время как документация для метода ruby ​​String # hash говорит, что он "вернет хэш на основе длины и содержимого строки", это явно не вся история. Указанный хеш строки не согласован между вызовами интерпретатора:

$ irb
ruby-1.9.2-p180 :001 > "foo".hash
 => 360517580588231756 
ruby-1.9.2-p180 :002 > ^D

$ irb
ruby-1.9.2-p180 :001 > "foo".hash
 => -2716152678666510148 

Это означает, что конкретное значение хеш-строки может отличаться, например, от серверов. Rails использует String#hash внутренне для сопоставления пути URL-адреса к одному из четырех хостов ресурсов (если приложение asset_host настроено), но эта функция намного менее эффективна, чем это может быть из-за несоответствий между машинами; разные серверы могут сопоставлять один и тот же URL-адрес с разными хозяевами ресурсов, снижая эффективность кешей, помутнение неба, чашки чашек с чаем преждевременно, избавляя репутацию от других прекрасных программистов.

Можете ли вы предложить альтернативную хеш-функцию, которая могла бы эффективно и быстро распространять хэши в типичном пространстве URL-адресов приложения, предпочтительно в том, что создает Fixnum, поскольку в конце концов я хочу отобразить его в один из четырех хостов активов?

4b9b3361

Ответ 2

Существует крошечная библиотека xxHash:

XXhash.xxh32('qwe') #=> 2396643526
XXhash.xxh64('qwe') #=> 9343136760830690622

Возможно, он будет иметь больше коллизий, но он будет в 10 раз быстрее, чем SHA1:

Benchmark.bm do |x|
  n = 100_000
  str = 'qweqweqwe'
  x.report('xxhash32') { n.times { XXhash.xxh32(str) } }
  x.report('xxhash64') { n.times { XXhash.xxh64(str) } }
  x.report('hexadigest') { n.times { Digest::SHA1.hexdigest(str) } }
end;1

#       user     system      total        real
# xxhash32  0.020000   0.000000   0.020000 (  0.021948)
# xxhash64  0.040000   0.000000   0.040000 (  0.036340)
# hexadigest  0.240000   0.030000   0.270000 (  0.276443)

Ответ 3

Вы можете попробовать to_i (36).

"Hash me please :(".to_i(36)
=> 807137