Reputation: 2869
I am trying out AsyncSeq and I am confused by a speed issue I am having. Here is a fiddle of the code below.
open System
open FSharpx.Control
let rec numbers n x = asyncSeq {
yield n
//printfn "%A" n
do! Async.Sleep(1)
if (n + 1 = x) then
yield n + 1
else
yield! numbers (n + 1) x
}
Async.Sleep(300) |> Async.RunSynchronously
for i in [0..300] do printfn "%A" i
numbers 0 300
|> AsyncSeq.iter (fun x -> printfn "%A" x)
|> Async.RunSynchronously
The top loop finishes clearly in a shorter amount of time. While the bottom async sequence takes longer. Is this normal? or am I missing something?
Upvotes: 0
Views: 214
Reputation: 243126
Asynchronous sequences have been designed for writing computations that involve some asynchronous waiting such as disk or network I/O. For this reason, it is quite sensible to expect some overhead when using asyncSeq
- in the typical use case, this is not very significant compared to the overhead of the asynchronous operations.
I had a quick look at your example and most of the overhead here is actually coming from Async.Sleep(1)
- this uses System.Threading.Timer
internally (to schedule the continuation to be called in a thread pool).
On my machine, the following code (with Async.Sleep
) takes about 4.6 seconds:
let rec numbers n x = asyncSeq {
yield n
do! Async.Sleep(1) // (sleep)
if (n < x) then yield! numbers (n + 1) x }
numbers 0 300
|> AsyncSeq.iter (fun x -> printfn "%A" x)
|> Async.RunSynchronously
But when you drop the Async.Sleep
call (line marked (sleep)
), the computation takes just 30ms, which is pretty much the same as the following for
loop:
for i in [0..300] do
printfn "%A" i
Now, if you add asynchronous sleeping to the for
loop, it takes 5 seconds too:
for i in [0..300] do
Async.Sleep(1) |> Async.RunSynchronously
printfn "%A" i
This is not too surprising - if you replaced asynchronous sleeping with Thread.Sleep
, then it would run faster (but synchronously). So, in summary:
asyncSeq
itself, but it is not that bigAsync.Sleep
Async.Sleep
can be misleading :-)Upvotes: 2