Руководство по использованию MailboxProcessor? - PullRequest
17 голосов
/ 10 августа 2010

Я только что обнаружил MailboxProcessor в F # и он используется в качестве "конечного автомата" ... но я не могу найти много информации о рекомендованном их использовании.

Например ... скажем, я делаю простую игру с 100 врагами на экране, если я использую MailboxProcessor для изменения положения и здоровья врага; дать мне 200 активных MailboxProcessor?

Есть ли какое-нибудь умное управление потоками, происходящее под капотом? я должен попытаться ограничить количество активных MailboxProcessor, которые у меня есть, или я могу продолжать бить их волей-неволей?

Заранее спасибо,

JD.

Ответы [ 4 ]

14 голосов
/ 10 августа 2010

MailboxProcessor для симуляции врага может выглядеть так:

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

Он не потребляет поток, ожидая прибытия сообщения (строка let! message =). Однако, как только сообщение прибудет, оно будет использовать поток (в пуле потоков). Если у вас есть 100 процессоров почтовых ящиков, которые все получают сообщение одновременно, они все будут пытаться проснуться и потреблять поток. Поскольку здесь обработка сообщений связана с ЦП, все сотни процессоров почтовых ящиков будут активированы и начнут порождать потоки (пул потоков). Это не очень хорошее представление.

Одной из ситуаций, в которой процессоры почтовых ящиков преуспевают, является ситуация, когда множество одновременно работающих клиентов отправляют сообщения одному процессору (представьте, что несколько параллельных веб-сканеров загружают страницы и отправляют результаты в очередь). Случай с врагами на экране выглядит по-другому - это множество объектов, реагирующих на один источник сообщений (движение игрока / время).

Другим примером, где тысячи MailboxProcessors - отличное решение, является связанный с вводом / выводом MailboxProcessor:

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

Здесь после получения сообщения агент очень быстро выдает поток, но ему все еще необходимо поддерживать состояние при асинхронных операциях. На практике это очень хорошо масштабируется - вы можете запускать тысячи и тысячи таких агентов: это отличный способ написать веб-сервер.

7 голосов
/ 10 августа 2010

Согласно

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

ты можешь их убить волей-неволей. Попытайся! Они используют ThreadPool. Я не пробовал это для приложения с графическим интерфейсом в реальном времени, но я не удивлюсь, если это «достаточно хорошо».

6 голосов
/ 01 июля 2013

скажем, я делаю простую игру с 100 врагами на экране, если я использую MailboxProcessor для изменения положения и здоровья врага; дать мне 200 активных MailboxProcessor?

Я не вижу смысла пытаться использовать MailboxProcessor для этого. Последовательный цикл, вероятно, будет намного проще и быстрее.

Есть ли хитрое управление потоками под капотом?

Да, много. Но предназначен ли он для асинхронного параллельного программирования (особенно для масштабируемого ввода-вывода), и ваша программа на самом деле этого не делает.

я должен попытаться ограничить количество активных почтовых процессоров, которые у меня есть, или я могу продолжать бить их по воле случая?

Вы можете убивать их невольно, но они далеко не оптимизированы, а производительность намного хуже, чем у серийного кода.

5 голосов
/ 10 августа 2010

Может быть это или это может помочь?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...