Algoritma hashing mana yang terbaik untuk keunikan dan kecepatan? Penggunaan contoh (baik) termasuk kamus hash.
Saya tahu ada hal-hal seperti SHA-256 dan sejenisnya , tetapi algoritma ini dirancang untuk aman , yang biasanya berarti mereka lebih lambat daripada algoritma yang kurang unik . Saya ingin algoritma hash dirancang untuk menjadi cepat, namun tetap cukup unik untuk menghindari tabrakan.
algorithms
hashing
Earlz
sumber
sumber
Jawaban:
Saya menguji beberapa algoritma yang berbeda, mengukur kecepatan dan jumlah tabrakan.
Saya menggunakan tiga set kunci yang berbeda:
"1"
ke"216553"
(pikirkan kode ZIP, dan bagaimana hash yang buruk mencatat msn.com )Untuk setiap korpus, jumlah tabrakan dan rata-rata waktu yang dihabiskan dicatat.
Saya menguji:
xor
bukan+
)Hasil
Setiap hasil berisi waktu hash rata-rata, dan jumlah tabrakan
Catatan :
Apakah tabrakan benar-benar terjadi?
Iya. Saya mulai menulis program pengujian saya untuk melihat apakah tabrakan hash benar - benar terjadi - dan bukan hanya konstruksi teoretis. Mereka memang terjadi:
FNV-1 tabrakan
creamwove
bertabrakan denganquists
FNV-1a tabrakan
costarring
bertabrakan denganliquid
declinate
bertabrakan denganmacallums
altarage
bertabrakan denganzinke
altarages
bertabrakan denganzinkes
Murmur2 tabrakan
cataract
bertabrakan denganperiti
roquette
bertabrakan denganskivie
shawl
bertabrakan denganstormbound
dowlases
bertabrakan dengantramontane
cricketings
bertabrakan dengantwanger
longans
bertabrakan denganwhigs
Tabrakan DJB2
hetairas
bertabrakan denganmentioner
heliotropes
bertabrakan denganneurospora
depravement
bertabrakan denganserafins
stylist
bertabrakan dengansubgenera
joyful
bertabrakan dengansynaphea
redescribed
bertabrakan denganurites
dram
bertabrakan denganvivency
Tabrakan DJB2a
haggadot
bertabrakan denganloathsomenesses
adorablenesses
bertabrakan denganrentability
playwright
bertabrakan dengansnush
playwrighting
bertabrakan dengansnushing
treponematoses
bertabrakan denganwaterbeds
Tabrakan CRC32
codding
bertabrakan dengangnu
exhibiters
bertabrakan denganschlager
Tabrakan SuperFastHash
dahabiah
bertabrakan dengandrapability
encharm
bertabrakan denganenclave
grahams
bertabrakan dengangramary
night
bertabrakan denganvigil
nights
bertabrakan denganvigils
finks
bertabrakan denganvinic
Pengacakan
Ukuran subyektif lainnya adalah seberapa besar hash didistribusikan secara acak. Memetakan HashTables yang dihasilkan menunjukkan bagaimana data didistribusikan secara merata. Semua fungsi hash menunjukkan distribusi yang baik ketika memetakan tabel secara linear:
Atau sebagai Peta Hilbert ( XKCD selalu relevan ):
Kecuali ketika hashing string angka (
"1"
,,"2"
...,"216553"
) (misalnya, kode pos ), di mana pola mulai muncul di sebagian besar algoritma hashing:SDBM :
DJB2a :
FNV-1 :
Semua kecuali FNV-1a , yang masih terlihat sangat acak bagi saya:
Bahkan, Murmur2 tampaknya memiliki keacakan yang lebih baik
Numbers
daripadaFNV-1a
:Ekstra
*
dalam tabel menunjukkan seberapa buruk keacakan itu. DenganFNV-1a
menjadi yang terbaik, danDJB2x
menjadi yang terburuk:Saya awalnya menulis program ini untuk memutuskan apakah saya bahkan harus khawatir tentang tabrakan: Saya lakukan.
Dan kemudian itu berubah menjadi memastikan bahwa fungsi hash cukup acak.
Algoritma FNV-1a
Hash FNV1 hadir dalam varian yang mengembalikan hash 32, 64, 128, 256, 512 dan 1024 bit.
The algoritma FNV-1a adalah:
Di mana konstanta
FNV_offset_basis
danFNV_prime
bergantung pada ukuran hash pengembalian yang Anda inginkan:Lihat halaman FNV utama untuk detailnya.
Semua hasil saya dengan varian 32-bit.
FNV-1 lebih baik dari FNV-1a?
Tidak. FNV-1a lebih baik. Ada lebih banyak tabrakan dengan FNV-1a saat menggunakan kata Inggris corpus:
Sekarang bandingkan huruf kecil dan besar:
Dalam hal ini FNV-1a tidak "400%" lebih buruk dari FN-1, hanya 20% lebih buruk.
Saya pikir takeaway yang lebih penting adalah bahwa ada dua kelas algoritma ketika datang ke tabrakan:
Dan kemudian ada seberapa merata hash tersebut:
Memperbarui
Berbisik? Tentu, mengapa tidak
Memperbarui
@whatshisname bertanya-tanya bagaimana kinerja CRC32 , menambahkan nomor ke tabel.
CRC32 cukup bagus . Beberapa tabrakan, tetapi lebih lambat, dan overhead tabel pencarian 1k.
Gunting semua hal yang salah tentang distribusi CRC - salah saya
Sampai hari ini saya akan menggunakan FNV-1a sebagai algoritma hash-table hash de facto saya . Tapi sekarang saya beralih ke Murmur2:
Dan saya benar- benar berharap ada yang salah dengan
SuperFastHash
algoritma yang saya temukan ; Sayang sekali menjadi sepopuler itu.Pembaruan: Dari beranda MurmurHash3 di Google :
Jadi saya kira itu bukan hanya saya.
Pembaruan: Saya menyadari mengapa
Murmur
lebih cepat dari yang lain. MurmurHash2 beroperasi pada empat byte sekaligus. Sebagian besar algoritma adalah byte demi byte :Ini berarti bahwa ketika kunci semakin lama Murmur mendapat kesempatan untuk bersinar.
Memperbarui
GUID dirancang untuk menjadi unik, bukan acak
Sebuah posting yang tepat waktu oleh Raymond Chen menegaskan fakta bahwa GUID "acak" tidak dimaksudkan untuk digunakan untuk keacakan mereka. Mereka, atau sebagian dari mereka, tidak cocok sebagai kunci hash:
Keacakan tidak sama dengan menghindari tabrakan; itulah sebabnya akan menjadi kesalahan untuk mencoba menemukan algoritma "hashing" Anda sendiri dengan mengambil beberapa bagian dari panduan "acak":
Catatan : Sekali lagi, saya memberi tanda "GUID acak" dalam tanda kutip, karena ini adalah varian "acak" dari GUID. Deskripsi yang lebih akurat adalah
Type 4 UUID
. Tetapi tidak ada yang tahu apa tipe 4, atau tipe 1, 3 dan 5. Jadi, lebih mudah untuk memanggil mereka GUID "acak".Semua Kata Bahasa Inggris mencerminkan
sumber
Jika Anda ingin membuat peta hash dari kamus yang tidak berubah, Anda mungkin ingin mempertimbangkan hashing sempurna https://en.wikipedia.org/wiki/Perfect_hash_function - selama konstruksi fungsi hash dan tabel hash, Anda dapat menjamin, untuk dataset yang diberikan, bahwa tidak akan ada tabrakan.
sumber
Berikut adalah daftar fungsi hash, tetapi versi singkatnya adalah:
sumber
CityHash oleh Google adalah algoritma yang Anda cari. Ini tidak baik untuk kriptografi tetapi bagus untuk menghasilkan hash yang unik.
Baca blog untuk lebih jelasnya dan kodenya tersedia di sini .
CityHash ditulis dalam C ++. Ada juga port C polos .
Tentang dukungan 32-bit:
sumber
plain C port
Tautan rusakSaya telah merencanakan perbandingan kecepatan pendek dari berbagai algoritma hashing ketika hashing file.
Plot individual hanya sedikit berbeda dalam metode membaca dan dapat diabaikan di sini, karena semua file disimpan dalam tmpfs. Karena itu patokan itu tidak terikat IO jika Anda bertanya-tanya.
Algoritma meliputi:
SpookyHash, CityHash, Murmur3, MD5, SHA{1,256,512}
.Kesimpulan:
CRC
instruksi SSE 4.2s , yang tidak dimiliki CPU saya. SpookyHash dalam kasus saya selalu sedikit sebelum CityHash.Sumber yang digunakan untuk plot:
sumber
Algoritma SHA (termasuk SHA-256) dirancang untuk menjadi cepat .
Bahkan, kecepatan mereka terkadang bisa menjadi masalah. Secara khusus, teknik umum untuk menyimpan token yang diturunkan kata sandi adalah dengan menjalankan algoritma hash standar cepat 10.000 kali (menyimpan hash hash hash hash hash dari ... password).
Keluaran:
sumber
bcrypt
,. Gunakan alat yang tepat..rodata
dan / atau biaya negara. Ketika Anda menginginkan algoritme untuk hashtable, Anda biasanya memiliki kunci yang sangat pendek, dan banyak di antaranya, tetapi tidak memerlukan jaminan tambahan dari kriptografi. Saya menggunakan Jenkins satu per satu waktu sendiri.Asumsi bahwa fungsi hash kriptografis lebih unik adalah salah, dan pada kenyataannya itu dapat ditunjukkan untuk sering mundur dalam praktik. Sebenarnya:
Yang berarti bahwa fungsi hash non-kriptografi mungkin memiliki lebih sedikit tabrakan daripada fungsi kriptografis untuk set data "baik" —set data yang dirancang untuknya.
Kami benar-benar dapat menunjukkan ini dengan data dalam jawaban Ian Boyd dan sedikit matematika: masalah Ulang Tahun . Rumus untuk jumlah pasangan bertabrakan yang diharapkan jika Anda memilih
n
bilangan bulat secara acak dari himpunan[1, d]
adalah ini (diambil dari Wikipedia):Memasukkan
n
= 216.553 dand
= 2 ^ 32 kita mendapatkan sekitar 5,5 tabrakan yang diharapkan . Tes Ian sebagian besar menunjukkan hasil di sekitar lingkungan itu, tetapi dengan satu pengecualian dramatis: sebagian besar fungsi mendapat nol tabrakan dalam tes angka berturut-turut. Probabilitas memilih 216.553 angka 32-bit secara acak dan mendapatkan nol tabrakan adalah sekitar 0,43%. Dan itu hanya untuk satu fungsi — di sini kita memiliki lima keluarga fungsi hash yang berbeda tanpa tabrakan!Jadi apa yang kita lihat di sini adalah bahwa hash yang diuji Ian berinteraksi baik dengan dataset angka berurutan — yaitu, mereka menyebar input yang berbeda minimal lebih luas daripada fungsi hash kriptografi ideal. (Catatan: ini berarti bahwa penilaian grafis Ian bahwa FNV-1a dan MurmurHash2 "terlihat acak" baginya dalam kumpulan data angka dapat disangkal dari datanya sendiri. Nol tabrakan pada kumpulan data ukuran itu, untuk kedua fungsi hash, sangat nonrandom!)
Ini bukan kejutan karena ini adalah perilaku yang diinginkan untuk banyak penggunaan fungsi hash. Sebagai contoh, kunci tabel hash seringkali sangat mirip; Jawaban Ian menyebutkan masalah yang pernah dialami MSN dengan tabel hash kode ZIP . Ini adalah penggunaan di mana penghindaran tabrakan pada input yang mungkin menang lebih dari perilaku acak.
Perbandingan instruktif lain di sini adalah kontras dalam tujuan desain antara CRC dan fungsi hash kriptografis:
Jadi untuk CRC sekali lagi baik untuk memiliki lebih sedikit tabrakan daripada acak dalam input minimal yang berbeda. Dengan hash crypto, ini tidak-tidak!
sumber
Gunakan SipHash . Ini memiliki banyak sifat yang diinginkan:
Cepat. Implementasi yang dioptimalkan memakan waktu sekitar 1 siklus per byte.
Aman. SipHash adalah PRF yang kuat (fungsi pseudorandom). Ini berarti bahwa ia tidak dapat dibedakan dari fungsi acak (kecuali Anda tahu kunci rahasia 128-bit). Karenanya:
Tidak perlu khawatir tentang probe tabel hash Anda menjadi waktu linier karena tabrakan. Dengan SipHash, Anda tahu bahwa Anda akan mendapatkan kinerja kasus rata-rata, terlepas dari input.
Kekebalan terhadap serangan penolakan layanan berbasis hash.
Anda dapat menggunakan SipHash (terutama versi dengan output 128-bit) sebagai MAC (Message Authentication Code). Jika Anda menerima pesan dan tag SipHash, dan tag itu sama dengan yang dari menjalankan SipHash dengan kunci rahasia Anda, maka Anda tahu bahwa siapa pun yang membuat hash juga memiliki kunci rahasia Anda, dan bahwa baik pesan maupun hash telah diubah sejak itu.
sumber
Itu tergantung pada data yang Anda hashing. Beberapa hashing berfungsi lebih baik dengan data tertentu seperti teks. Beberapa algoritma hashing secara khusus dirancang agar baik untuk data tertentu.
Paul Hsieh pernah membuat hash cepat . Dia mencantumkan kode sumber dan penjelasannya. Tapi itu sudah dipukuli. :)
sumber
Java menggunakan ini sederhana multiply-dan-menambahkan algoritma:
Mungkin ada yang jauh lebih baik di luar sana tetapi ini cukup luas dan tampaknya merupakan pertukaran yang baik antara kecepatan dan keunikan.
sumber
Pertama-tama, mengapa Anda perlu menerapkan hashing Anda sendiri? Untuk sebagian besar tugas, Anda harus mendapatkan hasil yang baik dengan struktur data dari perpustakaan standar, dengan asumsi ada implementasi yang tersedia (kecuali Anda hanya melakukan ini untuk pendidikan Anda sendiri).
Sejauh algoritma hashing aktual berjalan, favorit pribadi saya adalah FNV. 1
Berikut ini contoh implementasi versi 32-bit di C:
sumber
*
dan^
:h = (h * 16777619) ^ p[i]
==>h = (h ^ p[i]) * 16777619