Неблокирующее / асинхронное выполнение в Perl - PullRequest
12 голосов
/ 18 декабря 2011

Есть ли способ реализовать неблокирующее / асинхронное выполнение (без fork() 'ing) в Perl?

Раньше я был разработчиком Python в течение многих лет ... Python имеет действительно великолепную 'Twisted' среду, которая позволяет это делать (используя DEFERREDs . Когда я запускал поиск, чтобы увидеть, есть ли что-то в Perl, чтобы сделать то же самое, я наткнулся на POE framework - который казался "достаточно близким" к тому, что я искал. Но ... потратив некоторое время на чтение документации и "игру" с кодом, Я натолкнулся на «стену» - это следующее ограничение (из POE :: Session документация):

Обратные вызовы не являются преимущественными. Пока один работает, другие не будут отправлены. Это известно как совместная многозадачность. Каждый сеанс должен сотрудничать, возвращаясь к центральному диспетчерскому ядру.

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

Итак ... есть ли способ в Perl реализовать многозадачность (параллельное, неблокирующее, асинхронное выполнение кода) без fork() 'ing - аналогично DEFERREDs в Python?

Ответы [ 6 ]

11 голосов
/ 18 декабря 2011

Coro представляет собой смесь между POE и потоками.Читая документацию CPAN, я думаю, что IO :: Async выполняет реальное асинхронное выполнение. потоков можно использовать тоже - по крайней мере, Padre IDE успешно использует их.

8 голосов
/ 18 декабря 2011

Я не очень знаком с Twisted или POE, но базовое параллельное выполнение довольно просто с threads .Интерпретаторы, как правило, не компилируются с поддержкой потоков, поэтому вам нужно проверить это.Пакет forks является заменой многопоточности (реализует полный API), но использует процессы без проблем.Затем вы можете сделать что-то вроде этого:

my $thread = async {
    print "you can pass a block of code as an arg unlike Python :p";
    return some_func();
};
my $result = $thread->join();

Я определенно реализовал обратные вызовы из цикла событий в асинхронном процессе с использованием вилок, и я не понимаю, почему он не будет работать с потоками.

3 голосов
/ 19 декабря 2011

Twisted также использует совместную многозадачность, как POE & Coro.

Однако похоже, что Twisted Deferred использует (или может) использовать потоки.NB.Посмотрите этот ответ на вопрос SO Twisted: сделать код неблокирующим

Так что вам нужно будет пойти по тому же маршруту с POE (хотя использование вилка, вероятно, предпочтительнее ).

Таким образом, одним из решений POE будет использование: POE::Wheel::Run - переносимый код блокировки и программы в подпроцессах .

. Для альтернатив POE обратите внимание на AnyEvent и Reflex.

0 голосов
/ 20 августа 2013

Никакой другой обратный вызов не может запуститься, пока другой уже запущен!

Насколько я могу судить - это одинаково для всех языков (конечно, для каждого потока ЦП; современная сеть)серверы обычно порождают как минимум один процесс или поток на ядро ​​ЦП, поэтому для пользователей это будет похоже на работу, выполняемую параллельно, но длительный обратный вызов не прерывался, какое-то другое ядро ​​просто работало).

Вы не можете прервать прерывание, если только прерывание не было запрограммировано специально для его обработки.

Представьте себе код, выполнение которого занимает 1 минуту, и ПК с 16 ядрами - теперь представьте миллионлюди пытаются загрузить эту страницу, вы можете доставить результаты работы 16 людям и «перевести» все остальное, или вы можете аварийно завершить работу своего веб-сервера и никому не дать никаких результатов.Люди предпочитают не прерывать работу своего веб-сервера, поэтому они никогда не разрешают обратным вызовам прерывать другие обратные вызовы (не то, что они могли бы, даже если бы они пытались - вызывающий никогда не получает контроль над повторным вызовом до того, как предыдущий все равно закончится).)

0 голосов
/ 19 декабря 2011

POE хорошо, если вы хотите асинхронную обработку, но хорошо использовать только один процессор (ядро).Например, если приложение ограничено вводом / выводом, в большинстве случаев будет достаточно одного процесса.

0 голосов
/ 18 декабря 2011

Я полагаю, вы используете select для такого рода вещей.По аналогии с разветвлением есть нить .

...