Модераторы: korob2001, ginnie

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> perl threads, память, как работают 
:(
    Опции темы
Logo
Дата 2.4.2013, 10:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Возникла задача написать многопоточное приложение.
Через некоторое время встал вопрос с производительность и общими переменными между потоками.
Во первых, в perl все переменные по умолчанию различные для разных потоков.
Правильно я понимаю, что он копирует всю память в новый поток?
Код

use threads;
use Time::HiRes 'time';

$array = [1..1000000];

my @threads;
my $t1 = time;
push @threads, threads->create(sub {}) for 1..2;
my $t2 = time;
print ($t2-$t1)."\n";
$_->join for @threads;                


Судя по бенчмарку, это действительно так, при наличии $array поток создается существенно медленнее.
Выходит, на каждого пользователя онлайн, создается в памяти своя копия программы, всех модулей? Есть ли альтернатива?
PM MAIL   Вверх
Pfailed
Дата 2.4.2013, 11:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 22
Всего: 39



Да, при создании нового потока клонируется интерпретатор, со всеми вытекающими проблемами скорости создания потока и потребления памяти.
Альтернатива известная -- не использовать потоки. Что использовать вместо потоков зависит от задачи.
Какую проблему вы пытались решить с помощью потоков?



--------------------
PM MAIL   Вверх
DProf
Дата 2.4.2013, 15:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 39
Регистрация: 28.9.2012

Репутация: 1
Всего: 1



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

Код

use Time::HiRes 'time';
  
my $array = [1..1000000];
 
my $t1 = time;
my $pid = fork();
my $t2 = time;
 
if ( $pid == 0 )
{
    print "I am child\n";
    print "In child time eq " . ($t2-$t1) . "\n";
    exit;
}
else
{
    wait;
    print "I am parrent\n";
    print "In parrent time eq " . ($t2-$t1) . "\n";
}


У меня 0.004 секунды. Если даже памяти занято много, все равно fork это очень, очень быстро. Вы надеюсь не под win пишете? Там да - будет долго.

А общие переменные в разных процессах использовать вполне можно. IPC::Shareable например используйте. Но придется платить время за это. С объектами правда сложнее. Вот про объекты в разных процессах кое что http://www.perlmonks.org/?node_id=402290
PM MAIL   Вверх
Logo
Дата 2.4.2013, 16:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Увеличение времени запуска еще туда-сюда, но увеличение памати... fork вроде тоже копирует память? Нашел модуль для замены perl-тредов на форки forks::shared. Кроме того, расшаривания переменных он использует сокеты, подозреваю, что возможно время доступа к переменным увеличится.
Так же нашел такую штуку http://search.cpan.org/~mlehmann/Coro-6.23/Coro.pm

Добавлено @ 16:44
Правда в вики пишут
Цитата

Также существуют «облегченные» реализации fork() (Например в ядре Linux[1]), отображающие в новый процесс страницы памяти родительского, вместо того чтобы их копировать (новая страница создаётся только при изменении её содержимого одним из процессов), что существенно снижает время создания нового процесса (т. н. copy-on-write).

Как они работают? ОС да, Linux.

Это сообщение отредактировал(а) Logo - 2.4.2013, 16:45
PM MAIL   Вверх
Logo
Дата 2.4.2013, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 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
PM MAIL   Вверх
Pfailed
Дата 2.4.2013, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 22
Всего: 39



Для описанной задачи потоки конечно излишни. Для одновременной обработки множества сетевых соединений эффективно будет использовать non-blocking I/O. Так, например, работает высокопроизводительный сервер nginx. Под это дело в perl есть множество фреймворков: AnyEvent, POE, IO::Async и т.д. Есть отдельные высокопроизводительные event-based модули, такие как EV, Event.
Coro здесь тоже может помочь. Этот модуль позволяет писать программы в обычном процедурном стиле, который несколько отличается от событийного стиля предлагаемого вышеупомянутыми модулями, но при этом программы остаются такими же эффективными. Использование Coro очень похоже на использование модуля threads, но лишено его недостатков.


--------------------
PM MAIL   Вверх
DurRandir
Дата 2.4.2013, 21:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 14
Всего: 17



Эта тема поднималась на форуме неоднократно. Если очень коротко:

1) fork копирует только те страницы памяти, которые меняются в процессе-потомке (или родителе)
2) threads::shared тоже использует сокет для передачи данных между потоками (нет никакой разделяемой памяти)
3) Coro могут как подойти, так и не подойти. Этот модуль реализует корпоративную многозадачность - для него очень приятно писать (в отличие от того же нагромождения колбеков в AnyEvent), но без понимания отличия корпоративной многозадачности от вытесняющей - очень легко попасть в ситуацию "один запрос блокирует всё".
PM   Вверх
Logo
Дата 2.4.2013, 22:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



AnyEvent позволяет оборвать коллбек события, если по той или иной причине он зашел в бесконечный цикл? Не вижу в документации...

Цитата

fork копирует только те страницы памяти, которые меняются в процессе-потомке (или родителе)

По факту что это означает для Perl'а, что со временем форкнутый процесс займет столько же памяти, сколько и родительский? В результате перераспределения памяти для массивов, хешей.
PM MAIL   Вверх
DurRandir
Дата 2.4.2013, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 14
Всего: 17



Цитата
AnyEvent позволяет оборвать коллбек события, если по той или иной причине он зашел в бесконечный цикл? Не вижу в документации...

Halting problem алгоритмически неразрешима) Если вопрос во внешних таймерах по отношению к выполняющемуся коду (аналог alarm) - то только собствуенно alarm и есть, т.к. весь код выполняется в одном потоке. 

Цитата
По факту что это означает для Perl'а, что со временем форкнутый процесс займет столько же памяти, сколько и родительский? В результате перераспределения памяти для массивов, хешей. 

Зависит от приложения. Если (допустим) у нас процесс после старта занимает 90 мб (подгруженные библиотеки и модули, стартовая инциализация) - и потом создаёт данных на 10мб - вот эти 10 и будут выделены отдельно, + ещё сколько-то на то, что у перла своё управление памятью, и эти страницы он будет постоянно менять. А если базовый процесс очень легкий и у каждого потомка много своих данных - то и выигрышь будет минимальным. Нет общего ответа.
PM   Вверх
DurRandir
Дата 2.4.2013, 22:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 14
Всего: 17



(копия, вырезал)

Это сообщение отредактировал(а) DurRandir - 2.4.2013, 22:36
PM   Вверх
Logo
Дата 2.4.2013, 23:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Цитата

Halting problem алгоритмически неразрешима) Если вопрос во внешних таймерах по отношению к выполняющемуся коду (аналог alarm) - то только собствуенно alarm и есть, т.к. весь код выполняется в одном потоке. 


Т.е. выходит если он  использует не Core в качестве, выполнить задачу так же асинхронно нельзя. И один долгий запрос от одного клиента подвешивает весь сервер. Реального переключения между задачами нет.

Цитата

Зависит от приложения. Если (допустим) у нас процесс после старта занимает 90 мб (подгруженные библиотеки и модули, стартовая инциализация) - и потом создаёт данных на 10мб - вот эти 10 и будут выделены отдельно, + ещё сколько-то на то, что у перла своё управление памятью, и эти страницы он будет постоянно менять. А если базовый процесс очень легкий и у каждого потомка много своих данных - то и выигрышь будет минимальным. Нет общего ответа. 

Понятно, что если легкий процесс-потомок сразу же отработает, выигрыш будет, существенный. А если он достаточно легкий, но выполняется долго, и в процессе своей работы создает/удаляет переменные, изменяет размер массивов? Не вырастет ли он до размера исходного процесса в результате перераспределения памяти perl'ом?
PM MAIL   Вверх
Logo
Дата 3.4.2013, 00:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Однако, Coro похоже тоже не реальные потоки.

Код

#!/usr/bin/perl
use Coro;

async {
    print 1 while 1;
};

# scheduler;

print 2 while 2;


Выводит только "2".
И здесь пишут http://www.linux.org.ru/forum/development/6958940

Это сообщение отредактировал(а) Logo - 3.4.2013, 01:09
PM MAIL   Вверх
DurRandir
Дата 3.4.2013, 01:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 335
Регистрация: 27.9.2009

Репутация: 14
Всего: 17



Цитата
 А если он достаточно легкий, но выполняется долго, и в процессе своей работы создает/удаляет переменные, изменяет размер массивов? Не вырастет ли он до размера исходного процесса в результате перераспределения памяти perl'ом? 

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

Цитата
Coro похоже тоже не реальные потоки

Именно. Это green threads - аналог Эрланговских и т.п. И Coro, и AnyEvent длинную вычислительную задачу требуют выносить в отдельный поток исполнения. И это как раз случай корректного использования перловых потоков (ну или отдельного вычислительного демона рядом) - исключительно для тяжёлых вычислительных задач, создав для них отдельный фиксированный пул до загрузки тяжёлых модулей, экономя таким образом память. 

Итого - быстрый обмен с сетью на Coro/AnyEvent + тяжёлые/блокирующиеся действия - в отдельных потоках/процессах.
PM   Вверх
Pfailed
Дата 3.4.2013, 05:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 933
Регистрация: 19.7.2009

Репутация: 22
Всего: 39



Цитата(Logo @ 3.4.2013,  00:53)
Однако, Coro похоже тоже не реальные потоки.

Ну так документацию то почитайте, написано же "the only real threads in perl"  smile 
Для просветления могу посоветовать книгу "Разработка сетевых программ на Perl", там есть раздел про мультиплексирование


--------------------
PM MAIL   Вверх
Logo
Дата 3.4.2013, 13:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 694
Регистрация: 22.7.2008

Репутация: 3
Всего: 10



Цитата

Ну так документацию то почитайте, написано же "the only real threads in perl"

Как и ТС с ЛОР по ссылке, перевел как "только реальные потоки" smile... И при установке он зачем-то дает выбор, какие потоки использовать, pthreads, etc.

Это сообщение отредактировал(а) Logo - 3.4.2013, 13:42
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Perl"
korob2001
sharq
  • В этом разделе обсуждаются общие вопросы по языку Perl
  • Если ваш вопрос относится к системному программированию, задавайте его здесь
  • Если ваш вопрос относится к CGI программированию, задавайте его здесь
  • Интерпретатор Perl можно скачать здесь ActiveState, O'REILLY, The source for Perl
  • Справочное руководство "Установка perl-модулей", можно скачать здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, korob2001, sharq.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Perl: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0534 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.