![]() |
|
Модераторы: korob2001, ginnie |
![]()
|
|
| Logo |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 694 Регистрация: 22.7.2008 Репутация: 3 Всего: 10 |
Возникла задача написать многопоточное приложение.
Через некоторое время встал вопрос с производительность и общими переменными между потоками. Во первых, в perl все переменные по умолчанию различные для разных потоков. Правильно я понимаю, что он копирует всю память в новый поток?
Судя по бенчмарку, это действительно так, при наличии $array поток создается существенно медленнее. Выходит, на каждого пользователя онлайн, создается в памяти своя копия программы, всех модулей? Есть ли альтернатива? |
|||
|
||||
| Pfailed |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 19.7.2009 Репутация: 22 Всего: 39 |
Да, при создании нового потока клонируется интерпретатор, со всеми вытекающими проблемами скорости создания потока и потребления памяти.
Альтернатива известная -- не использовать потоки. Что использовать вместо потоков зависит от задачи. Какую проблему вы пытались решить с помощью потоков? |
|||
|
||||
| DProf |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 39 Регистрация: 28.9.2012 Репутация: 1 Всего: 1 |
Может не потоки использовать, а процессы нафоркать? Я конечно не вдавался глубоко в подробности механизма ветвления, но точно знаю что UNIX подобные системы поддерживают очень мощный fork.
У меня 0.004 секунды. Если даже памяти занято много, все равно fork это очень, очень быстро. Вы надеюсь не под win пишете? Там да - будет долго. А общие переменные в разных процессах использовать вполне можно. IPC::Shareable например используйте. Но придется платить время за это. С объектами правда сложнее. Вот про объекты в разных процессах кое что http://www.perlmonks.org/?node_id=402290 |
|||
|
||||
| Logo |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 694 Регистрация: 22.7.2008 Репутация: 3 Всего: 10 |
Увеличение времени запуска еще туда-сюда, но увеличение памати... fork вроде тоже копирует память? Нашел модуль для замены perl-тредов на форки forks::shared. Кроме того, расшаривания переменных он использует сокеты, подозреваю, что возможно время доступа к переменным увеличится.
Так же нашел такую штуку http://search.cpan.org/~mlehmann/Coro-6.23/Coro.pm Добавлено @ 16:44 Правда в вики пишут
Как они работают? ОС да, Linux. Это сообщение отредактировал(а) Logo - 2.4.2013, 16:45 |
|||
|
||||
| Logo |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 694 Регистрация: 22.7.2008 Репутация: 3 Всего: 10 |
Задача - написать фан сервер для игры. Пользователь присоединяется к серверу, пишет в сокет команды серверу и читает ответы.
Архитектура будет такая, что все команды будут выполнятся по умолчанию синхронно для одного пользователя, но если комада по вине сервера "повисла", то через n секунд она обрывается, в лог пишется сообщение об ошибке, выполняется следующая. Но для некоторых команд в фреймворке будет предусмотрена возможность задать асинхронное выполнение - для долгих команд, либо реализации аналога http long-pool. В самом тяжелом режиме, во время игры, игра посылает на сервер 2 команды ра в 7-12 секунд, для сброса буфера записи игры, и стастики. Также будет irc сервер, его игра использует для чата. Сама игра идет через DirctPlay... Оцениваемое максимальное количество игроков одновременно онлайн - 150 человек. Точно не более 500. Север - Pentium® Dual-Core CPU E5300 @ 2.60GHz 3GB оперативки, больше ничего тяжелого на нем вроде не крутится. Но хотелось бы иметь возможность запускать сервак и на более слабом сервере. Это сообщение отредактировал(а) Logo - 2.4.2013, 22:10 |
|||
|
||||
| Pfailed |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 19.7.2009 Репутация: 22 Всего: 39 |
Для описанной задачи потоки конечно излишни. Для одновременной обработки множества сетевых соединений эффективно будет использовать non-blocking I/O. Так, например, работает высокопроизводительный сервер nginx. Под это дело в perl есть множество фреймворков: AnyEvent, POE, IO::Async и т.д. Есть отдельные высокопроизводительные event-based модули, такие как EV, Event.
Coro здесь тоже может помочь. Этот модуль позволяет писать программы в обычном процедурном стиле, который несколько отличается от событийного стиля предлагаемого вышеупомянутыми модулями, но при этом программы остаются такими же эффективными. Использование Coro очень похоже на использование модуля threads, но лишено его недостатков. |
|||
|
||||
| DurRandir |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 335 Регистрация: 27.9.2009 Репутация: 14 Всего: 17 |
Эта тема поднималась на форуме неоднократно. Если очень коротко:
1) fork копирует только те страницы памяти, которые меняются в процессе-потомке (или родителе) 2) threads::shared тоже использует сокет для передачи данных между потоками (нет никакой разделяемой памяти) 3) Coro могут как подойти, так и не подойти. Этот модуль реализует корпоративную многозадачность - для него очень приятно писать (в отличие от того же нагромождения колбеков в AnyEvent), но без понимания отличия корпоративной многозадачности от вытесняющей - очень легко попасть в ситуацию "один запрос блокирует всё". |
|||
|
||||
| Logo |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 694 Регистрация: 22.7.2008 Репутация: 3 Всего: 10 |
AnyEvent позволяет оборвать коллбек события, если по той или иной причине он зашел в бесконечный цикл? Не вижу в документации...
По факту что это означает для Perl'а, что со временем форкнутый процесс займет столько же памяти, сколько и родительский? В результате перераспределения памяти для массивов, хешей. |
|||
|
||||
| DurRandir |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 335 Регистрация: 27.9.2009 Репутация: 14 Всего: 17 |
Halting problem алгоритмически неразрешима) Если вопрос во внешних таймерах по отношению к выполняющемуся коду (аналог alarm) - то только собствуенно alarm и есть, т.к. весь код выполняется в одном потоке.
Зависит от приложения. Если (допустим) у нас процесс после старта занимает 90 мб (подгруженные библиотеки и модули, стартовая инциализация) - и потом создаёт данных на 10мб - вот эти 10 и будут выделены отдельно, + ещё сколько-то на то, что у перла своё управление памятью, и эти страницы он будет постоянно менять. А если базовый процесс очень легкий и у каждого потомка много своих данных - то и выигрышь будет минимальным. Нет общего ответа. |
||||
|
|||||
| DurRandir |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 335 Регистрация: 27.9.2009 Репутация: 14 Всего: 17 |
(копия, вырезал)
Это сообщение отредактировал(а) DurRandir - 2.4.2013, 22:36 |
|||
|
||||
| Logo |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 694 Регистрация: 22.7.2008 Репутация: 3 Всего: 10 |
Т.е. выходит если он использует не Core в качестве, выполнить задачу так же асинхронно нельзя. И один долгий запрос от одного клиента подвешивает весь сервер. Реального переключения между задачами нет.
Понятно, что если легкий процесс-потомок сразу же отработает, выигрыш будет, существенный. А если он достаточно легкий, но выполняется долго, и в процессе своей работы создает/удаляет переменные, изменяет размер массивов? Не вырастет ли он до размера исходного процесса в результате перераспределения памяти perl'ом? |
||||
|
|||||
| Logo |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 694 Регистрация: 22.7.2008 Репутация: 3 Всего: 10 |
Однако, Coro похоже тоже не реальные потоки.
Выводит только "2". И здесь пишут http://www.linux.org.ru/forum/development/6958940 Это сообщение отредактировал(а) Logo - 3.4.2013, 01:09 |
|||
|
||||
| DurRandir |
|
||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 335 Регистрация: 27.9.2009 Репутация: 14 Всего: 17 |
Я уже привёл примерную оценку - сколько процесс займёт при старте, с учётом подгруженных модулей, - эта память, скорее всего, будет расшарена. Всё, что вы считаете дальше, в любой моделе, будет занимать свою память. Как шарить результаты рассчётов - возможны варианты.
Именно. Это green threads - аналог Эрланговских и т.п. И Coro, и AnyEvent длинную вычислительную задачу требуют выносить в отдельный поток исполнения. И это как раз случай корректного использования перловых потоков (ну или отдельного вычислительного демона рядом) - исключительно для тяжёлых вычислительных задач, создав для них отдельный фиксированный пул до загрузки тяжёлых модулей, экономя таким образом память. Итого - быстрый обмен с сетью на Coro/AnyEvent + тяжёлые/блокирующиеся действия - в отдельных потоках/процессах. |
||||
|
|||||
| Pfailed |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 933 Регистрация: 19.7.2009 Репутация: 22 Всего: 39 |
Ну так документацию то почитайте, написано же "the only real threads in perl" Для просветления могу посоветовать книгу "Разработка сетевых программ на Perl", там есть раздел про мультиплексирование |
|||
|
||||
| Logo |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 694 Регистрация: 22.7.2008 Репутация: 3 Всего: 10 |
Как и ТС с ЛОР по ссылке, перевел как "только реальные потоки" Это сообщение отредактировал(а) Logo - 3.4.2013, 13:42 |
|||
|
||||
![]()
|
| Правила форума "Perl" | |
|
|
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Perl: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |