MailboxProcessor memory usage

65 Views Asked by At

I was testing early-returning in F# async and noticed some strange memory usage behaviour with MailboxProcessor. Consider this program:

let mp = MailboxProcessor<bool>.Start (fun inbox ->
    let mutable count = 0
    let rec await () = async {
        let! msg = inbox.Receive ()
        count <- count + 1
        if msg then
            printfn "Count: %4i | Queued: %4i" count inbox.CurrentQueueLength
            return! await ()
        else return! finish () }
    and finish () = async {
        printfn "done" }
    await ())
let numPosts = 10_000
for _ = 1 to numPosts do
    mp.Post true
    System.Threading.Thread.Sleep 1
mp.Post false
System.Console.ReadLine () |> ignore

If you delete the else, the memory usage keeps growing, which I expected, because the return! finish ()s keep piling up on the stack, as you can see with all of the dones which are printed upon completion. But if you put the else back in, thus making await tail-recursive, the memory usage still grows apparently indefinitely, although not as quickly, while the queue length remains at zero.

If you delete the Sleep line and raise numPosts to 100_000, the memory usage rises quickly with queue length but then stays more or less steady while the messages are processed, even remaining high after completion. This surprises me a little as well, as I would have expected the memory usage to decline with queue length.

Can anyone explain these memory usage behaviours?

0

There are 0 best solutions below

Related Questions in F#