I gather you are working in the constraints of eio. But to me it just screams bureaucracy and wrong abstractions. Just for fun I tried to write your example with the newly released affect library, here’s the result:
open Affect
let count_primes n = …
let timed_count_primes n = …
let main () =
Fun.Async.main ~domain_count:2 @@ fun () ->
let start = Unix.gettimeofday () in
let task_a = Fun.Async.call (fun () -> timed_count_primes 2_000_000) in
let task_b = Fun.Async.call (fun () -> timed_count_primes 2_000_000) in
let a, time_a = Fun.Async.get task_a in
let b, time_b = Fun.Async.get task_b in
let total, sequential_estimate = a + b, time_a +. time_b in
let elapsed = Unix.gettimeofday () -. start in
if elapsed < sequential_estimate *. 0.75
then Format.printf "It's fast!@."
let () = if !Sys.interactive then () else main ()