Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MailboxProcessor usage guidelines?

Tags:

concurrency

f#

I've just discovered the MailboxProcessor in F# and it's usage as a "state machine" ... but I can't find much on the recommended usage of them.

For example... say I'm making a simple game with 100 on-screen enemies should I use a MailboxProcessor to change enemy position and health; giving me 200 active MailboxProcessor?

Is there any clever thread management going on under the hood? should I try and limit the amount of active MailboxProcessor I have or can I keep banging them out willy-nilly?

Thanks in advance,

JD.

like image 549
jdoig Avatar asked Aug 09 '10 20:08

jdoig


4 Answers

A MailboxProcessor for enemy simulation might look like this:

MailboxProcessor.Start(fun inbox ->
async {
  while true do
    let! message = inbox.Receive()
    processMessage(message)
})

It does not consume a thread while it waits for a message to arrive (let! message = line). However, once message arrives it will consume a thread (on a thread pool). If you have a 100 mailbox processors that all receive a message simultaneously, they will all attempt to wake up and consume a thread. Since here message processing is CPU bound, 100s of mailbox processors will all wake up and start spawning (thread pool) threads. This is not a great performance.

One situation mailbox processors excel in is the situation where there is a lot of concurrent clients all sending messages to one processor (imagine several parallel web crawlers all downloading pages and sinking results to a queue). On-screen enemies case appears different - it is many entities responding to a single source of messages (player movement/time ticks).

Another example where thousands of MailboxProcessors is a great solution is I/O bound MailboxProcessor:

MailboxProcessor.Start(fun inbox ->
async {
  while true do
    let! message = inbox.Receive()
    match message with
    |  ->
         do! AsyncWrite("something")
         let! response = AsyncResponse()
         ...
})

Here after receiving a message the agent very quickly yields a thread but still needs to maintain state across asynchronous operations. This will scale very very well in practice - you can run thousands and thousands of such agents: this is a great way to write a web server.

like image 86
Dmitry Lomov Avatar answered Oct 30 '22 21:10

Dmitry Lomov


As per

http://blogs.msdn.com/b/dsyme/archive/2010/02/15/async-and-parallel-design-patterns-in-f-part-3-agents.aspx

you can bang them out willy-nilly. Try it! They use the ThreadPool. I have not tried this for a real-time GUI game app, but I would not be surprised if this is 'good enough'.

like image 31
Brian Avatar answered Oct 30 '22 20:10

Brian


say I'm making a simple game with 100 on-screen enemies should I use a MailboxProcessor to change enemy position and health; giving me 200 active MailboxProcessor?

I don't see any reason to try to use MailboxProcessor for that. A serial loop is likely to be much simpler and faster.

Is there any clever thread management going on under the hood?

Yes, lots. But is it designed for asynchronous concurrent programming (particularly scalable IO) and your program isn't really doing that.

should I try and limit the amount of active MailboxProcessor I have or can I keep banging them out willy-nilly?

You can bang them out willy-nilly but they are far from optimized and performance is much worse than serial code.

like image 6
J D Avatar answered Oct 30 '22 19:10

J D


Maybe this or this can help?

like image 5
desco Avatar answered Oct 30 '22 20:10

desco