[英]F# AsyncSeq speed issue
I am trying out AsyncSeq and I am confused by a speed issue I am having. 我正在尝试AsyncSeq,但对速度问题感到困惑。 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?
还是我错过了什么?
Asynchronous sequences have been designed for writing computations that involve some asynchronous waiting such as disk or network I/O. 异步序列已被设计用于编写涉及一些异步等待的计算,例如磁盘或网络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. 因此,使用
asyncSeq
时会产生一些开销是非常明智的-在典型的用例中,与异步操作的开销相比,这不是很明显。
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). 我快速浏览了一下您的示例,这里的大部分开销实际上来自
Async.Sleep(1)
-这在内部使用System.Threading.Timer
(以计划在线程池中调用的延续)。
On my machine, the following code (with Async.Sleep
) takes about 4.6 seconds: 在我的机器上,以下代码(带有
Async.Sleep
)大约需要4.6秒:
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: 但是,当您放弃
Async.Sleep
调用(标为(sleep)
)时,计算仅需30ms,这与以下for
循环几乎相同:
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
循环中,则也需要5秒钟:
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). 这并不奇怪-如果您用
Thread.Sleep
替换了异步睡眠,那么它将运行得更快(但可以同步)。 So, in summary: 因此,总而言之:
asyncSeq
itself, but it is not that big asyncSeq
本身会有一些开销,但是那并不大 Async.Sleep
Async.Sleep
异步睡眠 Async.Sleep
can be misleading :-) Async.Sleep
类的玩具示例来衡量性能开销可能会产生误解:-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.