[perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 09.11.10 16:54
Оценка:
Для начала вопрос: есть подозрение, что операция fork() в Перле — довольно тормознутая вещь. Так ли это, и если так, то есть ли более-менее эффективные приёмы многопоточной обработки данных, не использующие fork()?

А теперь более подробно. Имеется простенький веб-сервер на Перле под Linux. В качестве иллюстративного примера я сделал урезанный вариант, который только и умеет, что принять GET-запрос, породить дочерний процесс, который займётся обработкой запроса, и вернуться к ожиданию нового подключения. Обработка же в дочернем процессе заключается в отправке клиенту содержимого HTML-файлика или XML-данных. Вот почти полный код примера:
  Скрытый текст
my $server = new IO::Socket::INET(Proto => 'tcp',
                                  LocalPort => 1234,
                                  Listen => SOMAXCONN,
                                  Reuse => 1);
while (my $client = $server->accept()) {
    # Читаем первую строку HTTP-запроса
    my $req_line = <$client>;
    $req_line =~ s/[\r\n]//g;

    # Читаем остальное (обработка POST-запросов выкинута из данного примера для простоты)
    my $line;
    while (<$client>) {
        s/[\r\n]//g;
        last if (m/^$/);
    }

    if (fork() != 0) {
        # Родительский процесс закрывает сокет и ждёт следующего коннекта
        close($client);
    }
    else {
        # Дочерний процесс занимается обработкой
        if ($req_line =~ m/^GET \/test HTTP\/\d\.\d$/) {
            # Для урла вида http://example.com:1234/test отдаём заранее приготовленный файлик
            my $data;
            open(FILE, '/home/user/public_html/test.html');
            read(FILE, $data, -s FILE);
            close(FILE);
            print $client 'HTTP/1.0 200 OK' . Socket::CRLF . 'Content-Type: text/html' . Socket::CRLF . Socket::CRLF;
            print $client $data;
        }
        else {
            # Для всех остальных запросов вываливаем простенький XML
            print $client 'HTTP/1.0 200 OK' . Socket::CRLF . 'Content-type: text/xml' . Socket::CRLF . Socket::CRLF;
            print $client '<?xml version="1.0" encoding="utf-8"?><root><success/></root>';
        }

        # Завершаем дочерний процесс
        close($client);
        close($server);
        exit;
    }
}

В файле test.html, который отправляется клиенту, находится JS-код, отсылающий серверу сотню AJAX-запросов и засекающий время, потраченное на их обработку. Вот упрощённый код скрипта:
  Скрытый текст
var cnt = 100;
var rest = cnt;
var t1;

function start_test() {
    t1 = (new Date()).getTime();
    for (var i = 0; i < cnt; ++i)
        ajax_call_get("/ajax?param=" + i);
    // Функция ajax_call_get — из самописного AJAX-фреймворка: посылает серверу запрос,
    // и при отсутствии ошибок вызывает пользовательскую функцию-обработчик с именем ajaxProcessResult.
}

function ajaxProcessResult(responseXML) {
    --rest;
    if (rest == 0) {
        var t2 = (new Date()).getTime();
        alert("Прошло " + (t2 - t1) + " мс");
    }
}

setTimeout("start_test()", 3000);

Так вот, запускаю я этот сервер, открываю в браузере урлу /test, через некоторое время получаю сообщение с измеренной длительностью, каковая в моём случае составляет от 11,5 до 12 секунд. Если же я отказываюсь от многопоточности (т.е. основной поток выполнения делает всё то, что делал дочерний процесс), то время выполнения тех же самых ста запросов резко падает до 0,7–0,8 секунды, т.е. в 15 раз, больше, чем на порядок! В реальном коде, конечно, обработка более мудрёная, чем в вышеприведённом примере, но цифры остаются почти такими же, и скорость реакции веб-приложения даже визуально отличается очень и очень сильно.

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

У меня есть подозрение, что в падении производительности виноват сам вызов fork(), а точнее — дублирование контекста. Напрямую проверить это я не могу, но когда я удалил из сервера часть стартового кода, инициализирующего разного рода структуры (благо в моём мини-примере они никак не используются), используемая процессом память снизилась с 14,5 метров до 8-ми, а измеренное время той же сотни запросов упало почти вдвое: до шести секунд. (Сразу скажу: перенос этой инициализации внутрь форка не подходит, т.к. эти данные нужны при обработке практически каждого запроса, а повторная их реинициализация на каждом запросе только замедляет выполнение, это я замерил). Моя последняя выдумка: выносить в форк исключительно обработку динамических запросов и отдачу больших файлов, а всякую статическую мелочь отдавать однопоточно. Это, действительно, дало неплохой прирост в скорости отклика интерфейса, поскольку на каждую страницу обычно приходится только один динамический запрос, все остальные — подгрузка картинок, скриптов и прочей шелухи.

Тем не менее, хочется идеала. Собственно, вопрос: можно ли как-то решить эту проблему, и если можно, то как?
Почему же, ё-моё, ты нигде не пишешь «ё»?
perl fork linux
Re: [perl] Тормознутые fork'и?
От: meandr  
Дата: 09.11.10 19:11
Оценка:
[perl] Тормознутые fork'и?
А top то у вас что показывает? Сдаеться мне что у вас проблема с буфиризацией
Posted via RSDN NNTP Server 2.1 beta
Re: [perl] Тормознутые fork'и?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 10.11.10 07:23
Оценка: 4 (1)
Здравствуйте, CaptainFlint, Вы писали:

CF>Для начала вопрос: есть подозрение, что операция fork() в Перле — довольно тормознутая вещь.


Не должно быть. По крайней мере в тех пределах, которые у вас получаются.
Хотя я не в курсе специфики именно Perl — может, он что-то серьёзно в этом случае перемучивает в своих данных...

CF> Так ли это, и если так, то есть ли более-менее эффективные приёмы многопоточной обработки данных, не использующие fork()?


Есть. Можно треды плодить, можно автоматы переключать...
старое доброе, не теряющее актуальности.

Если вспоминать HTTP сервера, то у апача prefork MPM создаёт fork'ом пачку процессов (их число может динамически меняться в зависимости от нагрузки), каждый из которых отрабатывает запросы последовательно.

CF>Так вот, запускаю я этот сервер, открываю в браузере урлу /test, через некоторое время получаю сообщение с измеренной длительностью, каковая в моём случае составляет от 11,5 до 12 секунд. Если же я отказываюсь от многопоточности (т.е. основной поток выполнения делает всё то, что делал дочерний процесс), то время выполнения тех же самых ста запросов резко падает до 0,7–0,8 секунды, т.е. в 15 раз, больше, чем на порядок! В реальном коде, конечно, обработка более мудрёная, чем в вышеприведённом примере, но цифры остаются почти такими же, и скорость реакции веб-приложения даже визуально отличается очень и очень сильно.


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

Попробуйте запустить, например, 5 таких тестов впараллель и сравните времена в двух вариантах исполнения. Если проблема именно в нагрузке, у вас каждый из тестов потратит десятки секунд (например, 60), если в задержках — каждый потратит ненамного больше тех же 12 секунд.
При этом тесте померяйте загрузку системы — затраты на user, system...

CF>Очевидно, что оставлять однопоточный веб-сервер ни в коем случае нельзя: отдельные запросы могут выполняться по нескольку минут, а то и часов (специфика веб-приложения), и иметь сдохший интерфейс в течение всего этого времени совершенно недопустимо. Но и настолько терять в производительности тоже не хочется, так что имею желание разобраться в причинах и найти какой-нибудь компромисс.


CF>У меня есть подозрение, что в падении производительности виноват сам вызов fork(), а точнее — дублирование контекста. Напрямую проверить это я не могу, но когда я удалил из сервера часть стартового кода, инициализирующего разного рода структуры (благо в моём мини-примере они никак не используются), используемая процессом память снизилась с 14,5 метров до 8-ми, а измеренное время той же сотни запросов упало почти вдвое: до шести секунд.


Ну а измерить напрямую? Снимите время прямо перед fork() и после него, запишите разницу...

CF>Тем не менее, хочется идеала. :) Собственно, вопрос: можно ли как-то решить эту проблему, и если можно, то как?


Куда копать — вам уже было несколько подсказок — действуйте по ним, потом расскажете, что накопалось.
The God is real, unless declared integer.
Re[2]: [perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 10.11.10 13:51
Оценка:
Здравствуйте, meandr, Вы писали:

M>А top то у вас что показывает? Сдаеться мне что у вас проблема с буфиризацией


А какие конкретно поля смотреть? Общая картина примерно такая:
top - 16:03:13 up 1 day, 22:30,  8 users,  load average: 0.62, 0.49, 0.29
Tasks: 141 total,  15 running, 126 sleeping,   0 stopped,   0 zombie
Cpu(s): 31.2%us, 66.0%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  2.8%si,  0.0%st
Mem:    762148k total,   661060k used,   101088k free,    23424k buffers
Swap:  1051644k total,    43872k used,  1007772k free,   224204k cached

66% в ядре — многовато, но как определить, чем оно там занимается?
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[2]: [perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 10.11.10 13:54
Оценка:
Здравствуйте, netch80, Вы писали:

CF>> Так ли это, и если так, то есть ли более-менее эффективные приёмы многопоточной обработки данных, не использующие fork()?


N>Есть. Можно треды плодить, можно автоматы переключать...

N>старое доброе, не теряющее актуальности.

N>Если вспоминать HTTP сервера, то у апача prefork MPM создаёт fork'ом пачку процессов (их число может динамически меняться в зависимости от нагрузки), каждый из которых отрабатывает запросы последовательно.


Думал о префорке, но остановила сложность реализации. У меня всё-таки не проект уровня Апача.
Насчёт тредов — где-то я слышал, что они внутрях перла теми же форками реализованы. Это не так? Попробую поэкспериментировать в этом направлении…

CF>>Так вот, запускаю я этот сервер, открываю в браузере урлу /test, через некоторое время получаю сообщение с измеренной длительностью, каковая в моём случае составляет от 11,5 до 12 секунд. Если же я отказываюсь от многопоточности (т.е. основной поток выполнения делает всё то, что делал дочерний процесс), то время выполнения тех же самых ста запросов резко падает до 0,7–0,8 секунды, т.е. в 15 раз, больше, чем на порядок! В реальном коде, конечно, обработка более мудрёная, чем в вышеприведённом примере, но цифры остаются почти такими же, и скорость реакции веб-приложения даже визуально отличается очень и очень сильно.


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


N>Попробуйте запустить, например, 5 таких тестов впараллель и сравните времена в двух вариантах исполнения. Если проблема именно в нагрузке, у вас каждый из тестов потратит десятки секунд (например, 60), если в задержках — каждый потратит ненамного больше тех же 12 секунд.

N>При этом тесте померяйте загрузку системы — затраты на user, system...

Запустил пять штук — время возросло в пять раз (для многопоточного — до 57 секунд, для однопоточного — ≈3,3 секунды). Нагрузка многопоточника такая же, как для одиночного запуска (см. соседний ответ
Автор: CaptainFlint
Дата: 10.11.10
): проц загружен по максимуму, треть в пользовательских процессах, две трети — в ядре.

CF>>У меня есть подозрение, что в падении производительности виноват сам вызов fork(), а точнее — дублирование контекста. Напрямую проверить это я не могу, но когда я удалил из сервера часть стартового кода, инициализирующего разного рода структуры (благо в моём мини-примере они никак не используются), используемая процессом память снизилась с 14,5 метров до 8-ми, а измеренное время той же сотни запросов упало почти вдвое: до шести секунд.


N>Ну а измерить напрямую? Снимите время прямо перед fork() и после него, запишите разницу...


Замерил, но получился очень большой разброс. В родительском процессе вызов форка занимает от половины миллисекунды до 88 мс (в среднем 19 мс), в дочернем — от 3 до 115 мс (в среднем 21,5).
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[3]: [perl] Тормознутые fork'и?
От: meandr  
Дата: 10.11.10 19:57
Оценка:
Re[2]: [perl] Тормознутые fork'и?
>>66% в ядре — многовато, но как определить, чем оно там занимается?
>>Не начинай дело, если не умеешь хотеть настолько, чтобы мочь.

Да это вообще то очень много. Чтобь понять что там происходит в ядре есть утилиты типа strace, ktrace, dtrace(все завист от вашей OS). Сидя в sys процесс например можут осуществлять подкачку(судя по размеру swap у вас не очень много оперативы)


Как вариант проверки скорости fork щапустить такой скрипт(stress.pl):

for(my $i=0; $i < 100; ++$i)
{
    $pid = fork();

    if($pid == 0)
    {
       select(undef, undef, undef, 0.1);
       exit(0);
    }
    elif($pid < 0)
    {
       print "error while create subprocess"
    };
};

while(waitpid() > 0){};


и замерить сколько будет исполняться:

time perl stress.pl
Posted via RSDN NNTP Server 2.1 beta
Re[3]: [perl] Тормознутые fork'и?
От: dilmah США  
Дата: 10.11.10 20:08
Оценка:
если у тебя много перловых данных, то сюрприз может быть в том что даже если ты используешь их только на чтение, то на уровне ниже перла они будут использоваться и на запись -- потому что перл делает подсчет ссылок. В результате будет write и copy on write, которых по хорошему не должно быть.
Re[4]: [perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 11.11.10 16:38
Оценка:
Здравствуйте, meandr, Вы писали:

>>>66% в ядре — многовато, но как определить, чем оно там занимается?


M>Да это вообще то очень много. Чтобь понять что там происходит в ядре есть утилиты типа strace, ktrace, dtrace(все завист от вашей OS). Сидя в sys процесс например можут осуществлять подкачку(судя по размеру swap у вас не очень много оперативы)


Так вроде ж, наоборот, своп не используется практически: эти 44 метра там как были с самого начала, так и остались, да ещё оперативы сотня свободна. Дисковой активности тоже не наблюдается.

M>Как вариант проверки скорости fork щапустить такой скрипт(stress.pl):

M>и замерить сколько будет исполняться:

M>time perl stress.pl


Прогнал, получилось очень шустро:
real    0m0.735s
user    0m0.177s
sys     0m0.382s

Но вот что любопытно: стоило мне добавить весь инициализационный код из сервера в этот скриптик, как секунд через 10 после запуска начался дикий своп со всеми его сопутствующими прелестями в виде капитального зависона всей системы до окончания работы скрипта. К счастью, длилось это меньше минуты, результаты же получились следующими:
real    0m42.047s
user    0m0.212s
sys     0m0.217s

Повторюсь, при работе веб-сервера подобных каверз не наблюдаю. При запуске моей сотни запросов процессор, конечно, загружен полностью, но система, хоть и подтормаживает, остаётся вполне жизнеспособной и на мои действия реагирует адекватно, никакого своппинга не наблюдается.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[5]: [perl] Тормознутые fork'и?
От: dilmah США  
Дата: 11.11.10 16:46
Оценка:
CF>Но вот что любопытно: стоило мне добавить весь инициализационный код из сервера в этот скриптик, как секунд через 10 после запуска начался дикий своп со всеми его сопутствующими прелестями в виде капитального зависона всей системы до окончания работы скрипта.

http://www.rsdn.ru/forum/dynamic/4032845.aspx
Автор: dilmah
Дата: 10.11.10
Re[4]: [perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 11.11.10 16:49
Оценка:
Здравствуйте, dilmah, Вы писали:

D>если у тебя много перловых данных, то сюрприз может быть в том что даже если ты используешь их только на чтение, то на уровне ниже перла они будут использоваться и на запись -- потому что перл делает подсчет ссылок. В результате будет write и copy on write, которых по хорошему не должно быть.


Ну, во-первых, не совсем ясно, при чём тут подсчёт ссылок. Это же новый, независимый процесс, со своим набором данных и своим отдельным счётчиком. Но даже если предположить, что он там что-то мудрит: объём занимаемой памяти у родительского процесса — 15 мегабайт, виртуальной — 43. Даже если она вся скопируется, ну сколько времени это займёт? Я ради интереса замерил чистое время копирования 64-мегабайтного блока в памяти (программкой на C), получилось 12 миллисекунд. Так что само по себе копирование ботлнеком не является. Либо Перл вместо простого копирования блока памяти перетряхивает всю структуру (непонятно зачем), либо проблема кроется в чём-то другом.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[6]: [perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 11.11.10 16:55
Оценка:
Здравствуйте, dilmah, Вы писали:

CF>>Но вот что любопытно: стоило мне добавить весь инициализационный код из сервера в этот скриптик, как секунд через 10 после запуска начался дикий своп со всеми его сопутствующими прелестями в виде капитального зависона всей системы до окончания работы скрипта.


D>http://www.rsdn.ru/forum/dynamic/4032845.aspx
Автор: dilmah
Дата: 10.11.10


На это я уже ответил, но даже если это так, пока непонятно, чем скрипт с самостоятельными форками отличается от сервера, делающего те же форки, но по запросам извне. Пока единственное предположение, что у сервера количество входящих подключений (и, следовательно, дочерних процессов) чем-то ограничено и память не успевает забиться, тогда как стресс-тест этого ограничения не содержит и быстро забивает систему своими копиями. Попробую поддать памяти виртуалке и перепроверить стресс-тест.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[5]: [perl] Тормознутые fork'и?
От: dilmah США  
Дата: 11.11.10 16:56
Оценка:
CF>Ну, во-первых, не совсем ясно, при чём тут подсчёт ссылок. Это же новый, независимый процесс, со своим набором данных и своим отдельным счётчиком.

ты точно понимаешь что такое copy on write?

CF> Но даже если предположить, что он там что-то мудрит: объём занимаемой памяти у родительского процесса — 15 мегабайт, виртуальной — 43. Даже если она вся скопируется, ну сколько времени это займёт? Я ради интереса замерил чистое время копирования 64-мегабайтного блока в памяти (программкой на C), получилось 12 миллисекунд. Так что само по себе копирование ботлнеком не является. Либо Перл вместо простого копирования блока памяти перетряхивает всю структуру (непонятно зачем), либо проблема кроется в чём-то другом.


я не понимаю. Ты сделал 100 форков. объем данных ты сам пишешь 15-40 мбайт. Умножь на 100. У тебя хватает памяти? Если нет, то почему ты удивляешься своппингу.
Re[5]: [perl] Тормознутые fork'и?
От: dilmah США  
Дата: 11.11.10 16:59
Оценка: 4 (1)
CF>Даже если она вся скопируется, ну сколько времени это займёт? Я ради интереса замерил чистое время копирования 64-мегабайтного блока в памяти (программкой на C), получилось 12 миллисекунд. Так что само по себе копирование ботлнеком не является.

при copy on write, копирование выполняется постранично (4 кб) по мере того как наступают page faults. Разумеется, это медленнее обычного копирования.
Re: [perl] Тормознутые fork'и?
От: любой  
Дата: 11.11.10 17:14
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>Для начала вопрос: есть подозрение, что операция fork() в Перле — довольно тормознутая вещь. Так ли это, и если так, то есть ли более-менее эффективные приёмы многопоточной обработки данных, не использующие fork()?


fork никак не медленнее просто создания нового процесса. Хотя и быстрее ему быть не с чего. Его имеет смысл использовать если процессу нужна долгая инициализация. В данном примере можно данные из файла прочитать до форка.
художников никогда не обижал
Re[6]: [perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 11.11.10 17:22
Оценка:
Здравствуйте, dilmah, Вы писали:

CF>>Ну, во-первых, не совсем ясно, при чём тут подсчёт ссылок. Это же новый, независимый процесс, со своим набором данных и своим отдельным счётчиком.


D>ты точно понимаешь что такое copy on write?


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

Почему я считаю, что подсчёт ссылок здесь ни при чём: если мы сделали копию всей памяти (неважно, реальную или "ссылочную"), то у нас все переменные, все хэши, все массивы — всё раздвоилось. Как в старом процессе была переменная A со счётчиком ссылок, пусть, 5, так и в новом процессе будет такая же переменная A с точно таким же (уже своим) счётчиком ссылок 5. Переменные нового процесса не ссылаются на переменные старого, и наоборот, поэтому значения счётчиков в результате самого форка поменяться не могут (не считая переменных, затронутых самим форком, таких как возвращаемое им значение, но таких переменных очень мало по сравнению с общим объёмом памяти). Поменяться счётчики могут лишь позже, когда начнутся присвоения переменных в процессе дальнейшего выполнения программы, но это уже другой вопрос.


CF>> Но даже если предположить, что он там что-то мудрит: объём занимаемой памяти у родительского процесса — 15 мегабайт, виртуальной — 43. Даже если она вся скопируется, ну сколько времени это займёт? Я ради интереса замерил чистое время копирования 64-мегабайтного блока в памяти (программкой на C), получилось 12 миллисекунд. Так что само по себе копирование ботлнеком не является. Либо Перл вместо простого копирования блока памяти перетряхивает всю структуру (непонятно зачем), либо проблема кроется в чём-то другом.


D>я не понимаю. Ты сделал 100 форков. объем данных ты сам пишешь 15-40 мбайт. Умножь на 100. У тебя хватает памяти? Если нет, то почему ты удивляешься своппингу.


Я, скорее, удивлялся не своппингу, а тому, что его в веб-сервере нет, хотя код по сути тот же самый.
В общем, перепроверил с памятью, увеличенной до двух гигов, — своппинга не было. Похоже, причина, действительно, в разном количестве одновременно работающих процессов. Когда запускаю веб-сервер со стресс-тестом, там одновременно крутится не больше двух десятков дочерних процессов, а когда консольный тест — то вплоть до 60–70, вот выскакивал за пределы 768 метров.
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[5]: [perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 11.11.10 17:24
Оценка:
CF>К счастью, длилось это меньше минуты, результаты же получились следующими:
CF>real    0m42.047s
CF>user    0m0.212s
CF>sys     0m0.217s

Перепроверил пример с инициализированными структурами на достаточном объёме оперативки, результаты такие:
real    0m15.027s
user    0m0.205s
sys     0m0.275s
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[6]: [perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 11.11.10 17:26
Оценка:
Здравствуйте, dilmah, Вы писали:


CF>>Даже если она вся скопируется, ну сколько времени это займёт? Я ради интереса замерил чистое время копирования 64-мегабайтного блока в памяти (программкой на C), получилось 12 миллисекунд. Так что само по себе копирование ботлнеком не является.


D>при copy on write, копирование выполняется постранично (4 кб) по мере того как наступают page faults. Разумеется, это медленнее обычного копирования.


А насколько медленнее? Есть какие-нибудь данные на этот счёт?
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[2]: [perl] Тормознутые fork'и?
От: CaptainFlint Россия http://flint-inc.ru/
Дата: 11.11.10 17:32
Оценка:
Здравствуйте, любой, Вы писали:

CF>>Для начала вопрос: есть подозрение, что операция fork() в Перле — довольно тормознутая вещь. Так ли это, и если так, то есть ли более-менее эффективные приёмы многопоточной обработки данных, не использующие fork()?


Л>fork никак не медленнее просто создания нового процесса. Хотя и быстрее ему быть не с чего. Его имеет смысл использовать если процессу нужна долгая инициализация. В данном примере можно данные из файла прочитать до форка.


Не совсем понял: из какого файла?
У меня чтение идёт из сокета, и его я уже перенёс в до-форковую часть, это ни малейшим образом ситуацию не улучшило (ну или улучшило в пределах погрешности).
Почему же, ё-моё, ты нигде не пишешь «ё»?
Re[7]: [perl] Тормознутые fork'и?
От: dilmah США  
Дата: 11.11.10 17:38
Оценка:
CF>Почему я считаю, что подсчёт ссылок здесь ни при чём: если мы сделали копию всей памяти (неважно, реальную или "ссылочную"), то у нас все переменные, все хэши, все массивы — всё раздвоилось. Как в старом процессе была переменная A со счётчиком ссылок, пусть, 5, так и в новом процессе будет такая же переменная A с точно таким же (уже своим) счётчиком ссылок 5. Переменные нового процесса не ссылаются на переменные старого, и наоборот, поэтому значения счётчиков в результате самого форка поменяться не могут (не считая переменных, затронутых самим форком, таких как возвращаемое им значение, но таких переменных очень мало по сравнению с общим объёмом памяти). Поменяться счётчики могут лишь позже, когда начнутся присвоения переменных в процессе дальнейшего выполнения программы, но это уже другой вопрос.

да, но перл производит запись даже тогда, когда кажется что он только читает. Когда перловые данные просто используются на чтение, то в них меняются счетчики ссылок => происходит запись => происходит page fault и копирование данных, которого в идеале можно было бы избежать.
Re[3]: [perl] Тормознутые fork'и?
От: любой  
Дата: 11.11.10 17:52
Оценка:
Здравствуйте, CaptainFlint, Вы писали:

CF>Не совсем понял: из какого файла?

        my $data;
        open(FILE, '/home/user/public_html/test.html');
        read(FILE, $data, -s FILE);
        close(FILE);


CF>У меня чтение идёт из сокета, и его я уже перенёс в до-форковую часть,

Интересно, как же оно тогда работает.

CF> это ни малейшим образом ситуацию не улучшило (ну или улучшило в пределах погрешности).

Ну конкретно я не могу сказать в чем проблема.
художников никогда не обижал
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.