Skip to content

Instantly share code, notes, and snippets.

@manofstick
Created July 21, 2018 01:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save manofstick/275fe8ed62091aec52cd382548719f2a to your computer and use it in GitHub Desktop.
Save manofstick/275fe8ed62091aec52cd382548719f2a to your computer and use it in GitHub Desktop.
open System
type KeyStruct(_1':int, _2':int, _3':int) = struct
member this._1 = _1'
member this._2 = _2'
member this._3 = _3'
end
type KeyGenericStruct<'a>(_1':'a, _2':'a, _3':'a) = struct
member this._1 = _1'
member this._2 = _2'
member this._3 = _3'
end
type KeyRecord = { _1 : int; _2 : int; _3 : int }
type KeyGenericRecord<'a> = { _1 : 'a; _2 : 'a; _3 : 'a }
let inline RunTest<'a when 'a : equality> iterationCount createAssociativeMap (createKey:_->_->_->'a) =
System.GC.Collect ()
System.GC.WaitForFullGCComplete () |> ignore
let data = [|
for a in 0..99 do
for b in 0..99 do
for c in 0..99 do
yield a,b,c |]
// shuffle
let r = System.Random (0)
for i = 0 to data.Length-1 do
let j = r.Next (i, data.Length)
let t = data.[i]
data.[i] <- data.[j]
data.[j] <- t
let keyValues =
data
|> Array.mapi (fun i k -> k, 0.5-(float i)/(float data.Length))
|> Array.toSeq
let sw = System.Diagnostics.Stopwatch.StartNew ()
let mapper = createAssociativeMap createKey keyValues
let creationTime = sw.ElapsedMilliseconds
let sw = System.Diagnostics.Stopwatch.StartNew ()
let mutable checksum = 0.
for i = 0 to iterationCount do
let a, b, c = r.Next 100, r.Next 100, r.Next 100
let key = createKey a b c
checksum <- checksum + (mapper key)
let accessTime= sw.ElapsedMilliseconds
checksum, creationTime, accessTime, (typeof<'a>.Name)
let inline RunNTrials<'a when 'a : equality> x = RunTest<'a> 1000000 x
let createDictionary create keyValues =
let d = System.Collections.Generic.Dictionary<_,_> ()
keyValues
|> Seq.map (fun ((_1,_2,_3),value) -> create _1 _2 _3, value)
|> Seq.iter (fun (key,value) -> d.[key] <- value)
(fun key -> d.[key])
let createDict create keyValues =
let d =
keyValues
|> Seq.map (fun ((_1,_2,_3),value) -> create _1 _2 _3, value)
|> dict
(fun key -> d.[key])
let createMap create keyValues =
let d =
keyValues
|> Seq.map (fun ((_1,_2,_3),value) -> create _1 _2 _3, value)
|> Map.ofSeq
(fun key -> d.[key])
let createCustomArray create keyValues =
let maxA = 1 + (keyValues |> Seq.map (fun ((a,_,_),_) -> a) |> Seq.max)
let maxB = 1 + (keyValues |> Seq.map (fun ((_,b,_),_) -> b) |> Seq.max)
let maxC = 1 + (keyValues |> Seq.map (fun ((_,_,c),_) -> c) |> Seq.max)
let createIndex a b c = a * maxB * maxC + b * maxC + c
let values : array<float> = Array.create (maxA * maxB * maxC) 0.
keyValues
|> Seq.iter (fun ((a,b,c),d) -> values.[createIndex a b c] <- d)
(fun (a,b,c) -> values.[a * maxB * maxC + b * maxC + c])
let inline RunDictionary<'a when 'a : equality> = RunNTrials<'a> createDictionary
let inline RunDict<'a when 'a : equality> = RunNTrials<'a> createDict
let inline RunMap<'a when 'a : comparison> = RunNTrials<'a> createMap
let inline RunCustomArray x = RunNTrials<_> createCustomArray x
[<EntryPoint>]
let main argv =
let checksum, creation, access, typeName =
match argv with
| [| _; "KeyRecord" |] -> RunMap (fun a b c -> { KeyRecord._1=a; _2=b; _3=c })
| [| _; "KeyGenericRecord" |] -> RunMap (fun a b c -> { KeyGenericRecord._1=a; _2=b; _3=c })
| [| _; "KeyStruct" |] -> RunMap (fun a b c -> KeyStruct(a, b, c))
| [| _; "KeyGenericStruct" |] -> RunMap (fun a b c -> KeyGenericStruct(a, b, c))
| [| _; "tuple" |] -> RunMap (fun a b c -> (a, b, c))
| [| _; "struct tuple" |] -> RunMap (fun a b c -> struct (a, b, c))
| [| _; "int32" |] -> RunMap (fun a b c -> a <<< 22 ||| b <<< 11 ||| c)
| [| _; "int64" |] -> RunMap (fun a b c -> (int64 a) <<< 44 ||| (int64 b) <<< 22 ||| (int64 c))
| _ -> failwith "unknown choice"
printfn "%s,%s,%s,%d,%d,%f" argv.[0] (if Environment.Is64BitProcess then "64-bit" else "32-bit") typeName creation access checksum
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment