Created
March 4, 2016 00:49
-
-
Save manofstick/e0f1cbf14febf3666c06 to your computer and use it in GitHub Desktop.
This file contains 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
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