Skip to content

Instantly share code, notes, and snippets.

@manofstick
Created March 4, 2016 00:49
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/e0f1cbf14febf3666c06 to your computer and use it in GitHub Desktop.
Save manofstick/e0f1cbf14febf3666c06 to your computer and use it in GitHub Desktop.
open System
open System.Threading
open System.Threading.Tasks
open System.Diagnostics
let bindBool (f: bool -> Task<bool>) (m: Task<bool>) =
if m.IsCompleted
then
f m.Result
else
let tcs = Runtime.CompilerServices.AsyncTaskMethodBuilder<_>.Create() // new TaskCompletionSource<_>() // NB do not allocate objects
let t = tcs.Task
let awaiter = m.GetAwaiter () // NB this is faster than ContinueWith
awaiter.OnCompleted(fun _ -> tcs.SetResult(f m.Result))
t.Unwrap()
let bindBool_ContinueWith (f: bool -> Task<bool>) (m: Task<bool>) =
if m.IsCompleted
then f m.Result
else (m.ContinueWith (fun (x:Task<bool>) -> f x.Result)).Unwrap ()
let bindBool_ContinueWithAwaiterResult (f: bool -> Task<bool>) (m: Task<bool>) =
if m.IsCompleted
then f m.Result
else (m.ContinueWith (fun (x:Task<bool>) -> f ((x.GetAwaiter()).GetResult()))).Unwrap ()
let run name f n =
GC.Collect ()
let busyWork count () =
let mutable result = false
for i = 1 to count do
result <- result <> ((i % 7) > (i % 3))
result
printfn "Running %s" name
let outer = Stopwatch.StartNew ()
for _' = 1 to n do
let sw = Stopwatch.StartNew ()
let r = Random 42 // make deterministic randomly
let c =
Array.init 10000 (fun _ ->
let workLoad = r.Next 100000
Task.Run (busyWork workLoad))
|> f
|> Array.sumBy (fun (t:Task<bool>) -> if t.Result then 1 else 0)
printfn "%d (checksum=%d)" sw.ElapsedMilliseconds c
printfn "%s total = %d\n" name outer.ElapsedMilliseconds
let runSet n =
run "bindBool" (Array.map (bindBool Task.FromResult)) n
run "bindBool_ContinueWith" (Array.map (bindBool_ContinueWith Task.FromResult)) n
run "bindBool_ContinueWithAwaiterResult" (Array.map (bindBool_ContinueWithAwaiterResult Task.FromResult)) n
[<EntryPoint>]
let main argv =
printfn "** PRIMING **"
runSet 1
printfn "** TIMINGS **"
runSet 10
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment