LINUX.ORG.RU

Perl, fork limit

 , , , ,


0

1

Привет, ЛОР!

Есть многопоточный код на Perl, который использует встроеную систему форков. Критически важные функции - форкаются в отдельный процесс и там исполняются. Все бы хорошо, да только слишком много их (процессов) создается. В итоге их становится на порядок больше чем ядер CPU. Хотелось бы как-то ограничить количество форков. Реализовать некую очередь, которая бы следила, что в каждый момент времени работало только N форков.

Интересуют идеи как такое можно сделать с помощью стандартной библиотеки перла, не прибегая к сторонним модулям на cpan (типа Parallel::ForkManager и проч.) и тредам (ибо глюкодром).

Any idea :) ?


Ответ на: комментарий от outtaspace

Там что-то мутят с пайпом и pid-файлом процесса. Как работает пайп я знаю, но каким боком там pid-файл? Если ты в теме, можешь идею на русском изложить)?

djnoob ()
Ответ на: комментарий от djnoob

Менеджер процессов рулит своими чайлдами - воркерами. PID-файл нужен для управления менеджером. Смотри на пропертю pool и метод _spawn, не отвлекайся.

outtaspace ★★★ ()
Ответ на: комментарий от outtaspace

Как я и предполагал - решается влоб через очередь. Накидал пример на коленке, для демонстрации идеи.

#!/bin/env perl -w 

# use strict;
use warnings;

use POSIX ':sys_wait_h';

local $SIG{CHLD} = sub { 1 while (waitpid(-1, WHONANG) > 0)};

my $queue = [];
my $MAX_PROCESS  = 3;

sub myfunc1 {for(1..100000000){}print "Hello 1\n";}
sub myfunc2 {for(1..100000000){}print "Hello 2\n";}
sub myfunc3 {for(1..100000000){}print "Hello 3\n";}
sub myfunc4 {for(1..100000000){}print "Hello 4\n";}
sub myfunc5 {for(1..100000000){}print "Hello 5\n";}
sub myfunc6 {for(1..100000000){}print "Hello 6\n";}
sub myfunc7 {for(1..100000000){}print "Hello 7\n";}
sub myfunc8 {for(1..100000000){}print "Hello 8\n";}
sub myfunc9 {for(1..100000000){}print "Hello 9\n";}
sub myfunc10 {for(1..100000000){}print "Hello 10\n";}

push @$queue, \&myfunc1, \&myfunc2, \&myfunc3, \&myfunc4, \&myfunc5, \&myfunc6, \&myfunc7,\&myfunc8,\&myfunc9,\&myfunc10;

while (my @batch = splice(@$queue, 0, $MAX_PROCESS)) {
    my $pids = [];

    for (@batch) {
        my $pid = fork();
        if ($pid) {
            push @$pids, $pid;
        } else {
            $_->();
            exit(0);        
        }
    }

    for (@$pids) {
        if ( waitpid($_, 0) > 0 ) {
            my ($rc, $sig, $core) = ($? >> 8, $? & 127, $? & 128);
            if ($core) {
                print "$_ dumped core\n";
            } elsif ($sig == 9) {
                print "$_ was murdered!\n";
            } else {
                print "$_ returned $rc";
                print ($sig?" after receiving signal $sig":"\n");
            }
        } else {
            print "$_ exit normally\n";
        }
    }
}


Еще вопрос: как застваить дружить use strict и WHONANG ?

djnoob ()
Ответ на: комментарий от djnoob
local $SIG{CHLD} = sub { 1 while (waitpid(-1, POSIX::WNOHANG) > 0)};

Внутри сигнала strict не видет use'ов

ilux ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.