Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Нужен совет


Автор: infarch 2.4.2015, 11:21
Здравствуйте.

Я пишу скрипт, который будет выполнять несколько задач паралельно. И вот возник вопрос: а что лучше с точки зрения производительности и стабильности, fork или потоки? Работать скрипт должен под линуксом и виндой.

В случае форков, я запускаю задачи и слежу за их завершением через waitpid($pid, WNOHANG). Как задача отработала, стартую другую. Тут я вижу плюс в том что если один форк умер, то на систему в целом это не повлияет.

Другой вариант - запустить пул из нескольких потоков и кидать задачи в расшаренную очередь (Thread::Queue). Плюс в том что не создаются потоки каждый раз.

Мне интересно услышать мнение людей которые решали подобные задачи и могут подсказать лучший путь. Буду благодарен за всякий конструктивный совет.

Автор: tzirechnoy 2.4.2015, 11:52
Процэссы, потоки, fsm разных видов (ручные или на callbackах), невытесныющие (кооперативные) потоки, лёгкие вытесняющие псевдопроцэссы a-la erlang -- активно используются в современном программировании потому, что у каждой из этих технологий есть какие-то свои плюсы, и потому для каждой технологии находятся свои задачи.

Из этого следует, что не зная спецыфики задачи -- нельзя сказать, что подойдёт, а что нет.

Но да, я никому не советую связываться с системными потоками без крайней нужды. Выигрыш от упрощения написания параллельности скорее всего с лихвой съестся проигрышэм в синхронизацыи и отладке. Крайняя нужда по скорости -- требует, как минимум, результатов профайлера, и вообще безсмысленно делать это не perl -- просто перепишыте нужные куски на C, и при наличии до 20 процэссоров получите не меньшый выигрыш в скорости.

Если IPC и обработка запросов к рабочим процэссам много не займут (по сравнению с остальной работой) -- можно вообще соорудить комплект из nginx,fastcgi+CGI::Fast и Net::HTTP::NB. Плюсами -- удобное распараллеливание на множэство хостов.

С другой стороны, у Вас практически работающий fork -- так что можно и на нём для начала остановиться.

Автор: infarch 2.4.2015, 12:05
Цитата(tzirechnoy @  2.4.2015,  11:52 Найти цитируемый пост)
не зная спецыфики задачи -- нельзя сказать, что подойдёт, а что нет


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

Система будет запускаться на нескольких машинах, одна явно не стянет всю нагрузку. В пределах одной машины хотелось бы сделать систему многопоточной для более полной утилизации ядер процессора. Именно поэтому я и начал это изучение.

К вебу это не имеет отношения, никаких ngnix/fastcgi не требуется. Просто система для выполнения рутинных тяжеловесных задач.

Автор: arto 2.4.2015, 12:15
Gearman?

Автор: baldina 2.4.2015, 12:20
Цитата(infarch @  2.4.2015,  12:05 Найти цитируемый пост)
для более полной утилизации ядер процессора

удобнее иметь дело с пулом потоков

Автор: infarch 2.4.2015, 12:36
Цитата(arto @  2.4.2015,  12:15 Найти цитируемый пост)
Gearman


Это интересно, спасибо! Почитаю...

Автор: infarch 2.4.2015, 13:30
Цитата(arto @  2.4.2015,  12:15 Найти цитируемый пост)
Gearman


Это таки немного не то... Конечно идея хорошая, но мне нужно кое что такое чего там нет. Например если не запущен ни один сервер, то поставить задачу не выйдет, не так ли? Задачу нельзя запрограммировать на время, сделать повторяющейся... Еще мне нужен прогресс, отмена, а самое главное - получить результат задачи которая выполнялась асинхронно когда-то раньше, по её айди. Наверно можно сваять кучу костылей над gearman чтоб это все получить, но наверно таки проще написать с нуля.

Автор: alezzz 2.4.2015, 15:05
У Windows вроде с fork-ом не все гладко:
Код

On some platforms such as Windows where the fork() system call is not available, Perl can be built to emulate fork() at the interpreter level.

Есть пара вещей написаных с использованием потоков, нужен был риалтайм (прием/передача udp), как это сделать (и можно ли) например на coro или anyevent не разобрался, поэтому делал на threads, обменивался данными через threads::shared, тут могу лишь сказать лучше как можно реже использовать шареные переменные, т.е. собрал данные и отправил, а не постоянно в цикле юзать шару. Ну а что там в Thread::Queue не могу сказать, не использовал. Еще недавно открыл для себя memcached.
И конечно правильоне решение "запустить пул из нескольких потоков и кидать задачи", я сделал немного криво, потоки удалялись и добавлялись в процессе работы, в итоге получил утечку памяти, победить не получилось, свел к минимуму, хотя может это особенности использования памяти в FreeBSD.

Автор: tzirechnoy 2.4.2015, 19:10
Цитата
Насчет специфики: это будет вспомогательная система для выполнения задач, тип которых в принципе может быть любой.


batch system (aka job scheduler) пишэте? Это правильно.
Прочитайте, для начала, http://en.wikipedia.org/wiki/Job_scheduler. И, хотя бы просмотрите писание JCL. Много времени не займёт, а на полезные мысли можэт натолкнуть.

Там ещё список имеющихся batch system есть -- но, право, в OpenSource с этим сейчас всё не очень хорошо, потому писать своё есть смысл.

И да, почему-то в списке job scheduler там нет Hadoop -- хотя он, в итоге, таковым является, и при этом является наиболее распространённым продуктом OpenSource такого рода. Но это я так, к слову, Hadoop довольно спецыфичен и в общем незачем его особенно смотреть.

Добавлено через 1 минуту и 38 секунд
Цитата
У Windows вроде с fork-ом не все гладко:


Да, на Windows лучшэ использовать сразу CreateProcess. Не такой уж они и важный, этот fork.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)