Last active
          August 29, 2015 14:08 
        
      - 
      
- 
        Save hodzanassredin/90d45c5c6f8d7eb7fbef to your computer and use it in GitHub Desktop. 
    chcking perf of hash funcs
  
        
  
    
      This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
      Learn more about bidirectional Unicode characters
    
  
  
    
  | //output | |
| //good keys | |
| //struct custom 1.506934 sec 0.000000 collisions | |
| //struct auto 4.832881 sec 0.776863 collisions | |
| //struct auto explicit 3.166931 sec 0.776863 collisions | |
| //bad keys | |
| //struct custom 3.631251 sec 0.061893 collisions | |
| //struct auto 10.340693 sec 0.777034 collisions | |
| //struct auto explicit 8.893612 sec 0.777034 collisions | |
| open System | |
| open System.Collections.Generic | |
| let check keys e name = | |
| let dict = new Dictionary<_,_>(Array.length keys, e)//, HashIdentity.Structural) | |
| let stopWatch = System.Diagnostics.Stopwatch.StartNew() | |
| let add k = dict.Add(k, 1.02) | |
| Array.iter add keys | |
| stopWatch.Stop() | |
| let hsahes = new HashSet<int>() | |
| let add_hash x = hsahes.Add(e.GetHashCode(x)) |> not | |
| let collisions = Array.filter add_hash keys |> Array.length | |
| printfn "%s %f sec %f collisions" name stopWatch.Elapsed.TotalSeconds (double(collisions) / double(keys.Length)) | |
| type StructTuple<'T,'T2> = | |
| struct | |
| val fst: 'T | |
| val snd : 'T2 | |
| new(fst: 'T, snd : 'T2) = {fst = fst; snd = snd} | |
| end | |
| let bad_keys = seq{ | |
| let rnd = new Random(); | |
| while true do | |
| let j = uint32(rnd.Next(0, 3346862)) | |
| let k = uint16 (rnd.Next(0, 658)) | |
| yield StructTuple(j,k) | |
| } | |
| let good_keys = seq{ | |
| for k in 0us..658us do | |
| for j in 0u.. 3346862u do | |
| yield StructTuple(j,k) | |
| } | |
| module CmpHelpers = | |
| let inline combine (h1:int) (h2:int) = (h1 <<< 5) + h1 ^^^ h2; | |
| type StructTupleComparer<'T,'T2>() = | |
| let cmparer = EqualityComparer<Object>.Default | |
| interface IEqualityComparer<StructTuple<'T,'T2>> with | |
| member this.Equals (a,b) = cmparer.Equals(a.fst, b.fst) && cmparer.Equals(a.snd, b.snd) | |
| member this.GetHashCode (x) = CmpHelpers.combine (cmparer.GetHashCode(x.fst)) (cmparer.GetHashCode(x.snd)) | |
| type AutoGeneratedStructTupleComparer<'T,'T2>() = | |
| let cmparer = LanguagePrimitives.GenericEqualityComparer | |
| interface IEqualityComparer<StructTuple<'T,'T2>> with | |
| member this.Equals (a:StructTuple<'T,'T2>,b:StructTuple<'T,'T2>) = | |
| LanguagePrimitives.HashCompare.GenericEqualityERIntrinsic<'T> a.fst b.fst | |
| && LanguagePrimitives.HashCompare.GenericEqualityERIntrinsic<'T2> a.snd b.snd | |
| member this.GetHashCode (x:StructTuple<'T,'T2>) = | |
| let mutable num = 0 | |
| num <- -1640531527 + (LanguagePrimitives.HashCompare.GenericHashWithComparerIntrinsic<'T2> cmparer x.snd + ((num <<< 6) + (num >>> 2))) | |
| -1640531527 + (LanguagePrimitives.HashCompare.GenericHashWithComparerIntrinsic<'T> cmparer x.fst + ((num <<< 6) + (num >>> 2))); | |
| let uniq (sq:seq<'a>) = Array.ofSeq (new HashSet<_>(sq)) | |
| [<EntryPoint>] | |
| let main argv = | |
| let count = 15000000 | |
| let keys = good_keys |> Seq.take count |> uniq | |
| printfn "good keys" | |
| check keys (new StructTupleComparer<_,_>()) "struct custom" | |
| check keys HashIdentity.Structural "struct auto" | |
| check keys (new AutoGeneratedStructTupleComparer<_,_>()) "struct auto explicit" | |
| let keys = bad_keys |> Seq.take count |> uniq | |
| printfn "bad keys" | |
| check keys (new StructTupleComparer<_,_>()) "struct custom" | |
| check keys HashIdentity.Structural "struct auto" | |
| check keys (new AutoGeneratedStructTupleComparer<_,_>()) "struct auto explicit" | |
| Console.ReadLine() |> ignore | |
| 0 // return an integer exit code | 
  
    Sign up for free
    to join this conversation on GitHub.
    Already have an account?
    Sign in to comment