I also managed to try https://github.com/ysbaddaden/siphash.cr and it’s working better than FNV on big strings. I’ve made a comparison of these three: OpenSSL::SHA1
, FNV
and SipHash
on 10, 100, 500 and 10k-sized strings. I’ve made my conclusions and I’m gonna give the developer a choice on what algorithm to use for a job.
Benchmark code
require "openssl"
require "./fnv1a"
require "siphash"
require "benchmark"
require "random/secure"
payload_10 = ("a" * 10).to_slice
payload_100 = ("a" * 100).to_slice
payload_500 = ("a" * 500).to_slice
payload_10000 = ("a" * 10000).to_slice
sha_1digest = OpenSSL::Digest.new("SHA1")
siphash_key = StaticArray(UInt8, 16).new(0)
Benchmark.ips do |x|
x.report "sha1 10" do
hash = sha_1digest.update(payload_10).to_s
end
x.report "sha1 100" do
hash = sha_1digest.update(payload_100).to_s
end
x.report "sha1 500" do
hash = sha_1digest.update(payload_500).to_s
end
x.report "sha1 10000" do
hash = sha_1digest.update(payload_10000).to_s
end
x.report "fnv1a 10" do
hash = FNV.fnv1a_32(payload_10).to_s
end
x.report "fnv1a 100" do
hash = FNV.fnv1a_32(payload_100).to_s
end
x.report "fnv1a 500" do
hash = FNV.fnv1a_32(payload_500).to_s
end
x.report "fnv1a 10000" do
hash = FNV.fnv1a_32(payload_10000).to_s
end
x.report "siphash 10" do
hash = SipHash(1, 3).siphash(payload_10, siphash_key).to_s
end
x.report "siphash 100" do
hash = SipHash(1, 3).siphash(payload_100, siphash_key).to_s
end
x.report "siphash 500" do
hash = SipHash(1, 3).siphash(payload_500, siphash_key).to_s
end
x.report "siphash 10000" do
hash = SipHash(1, 3).siphash(payload_10000, siphash_key).to_s
end
end
Results:
sha1 10 854.76k ( 1.17µs) (± 0.82%) 368 B/op 17.50× slower
sha1 100 710.62k ( 1.41µs) (± 1.20%) 368 B/op 21.05× slower
sha1 500 468.16k ( 2.14µs) (± 0.96%) 368 B/op 31.95× slower
sha1 10000 54.48k ( 18.36µs) (± 4.26%) 368 B/op 274.55× slower
fnv1a 10 14.96M ( 66.86ns) (± 1.15%) 32 B/op fastest
fnv1a 100 4.04M (247.47ns) (± 1.57%) 32 B/op 3.70× slower
fnv1a 500 971.51k ( 1.03µs) (± 2.13%) 32 B/op 15.40× slower
fnv1a 10000 53.39k ( 18.73µs) (± 2.13%) 32 B/op 280.18× slower
siphash 10 8.74M (114.47ns) (± 0.86%) 32 B/op 1.71× slower
siphash 100 5.23M (191.16ns) (± 0.81%) 48 B/op 2.86× slower
siphash 500 2.24M (445.82ns) (± 0.91%) 48 B/op 6.67× slower
siphash 10000 161.62k ( 6.19µs) (± 2.34%) 48 B/op 92.55× slower