# How to easily get consistent object hash?

**URL:** <https://forum.crystal-lang.org/t/how-to-easily-get-consistent-object-hash/314>\
**Category:** Offtopic\
**Created:** [January 19, 2019, 3:58pm UTC](https://forum.crystal-lang.org/t/how-to-easily-get-consistent-object-hash/314 "2019-01-19T15:58:02Z")\
**Posts on this page:** 1\
**Showing post:** 16

<div class="post-metadata">

**Author:** ![vladfaust](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/vladfaust/32/48_2.png) [@vladfaust](https://forum.crystal-lang.org/u/vladfaust)\
**Post date:** [January 19, 2019, 8:35pm UTC](https://forum.crystal-lang.org/t/how-to-easily-get-consistent-object-hash/314/16 "2019-01-19T20:35:56Z")

</div>

I also managed to try [https://github.com/ysbaddaden/siphash.cr](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**
>
> ```crystal
> 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:

```auto
      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

```

---

_[View the full topic](https://forum.crystal-lang.org/t/how-to-easily-get-consistent-object-hash/314)._
