Вы не указывают, сколько процессов могут быть, но ни один ресурс не безграничен, и вы должны ограничить количество или вы будете видеть быстрое снижение производительности, как вы достигнете насыщения.
Это еще более важно, когда вы выходите в сеть, так как вы можете раздражать сервер (и все также перестанет быстро развиваться). Возможно, до нескольких десятков процессов одновременно?
Тогда один из вариантов - ограничить количество параллельных загрузок, используя Parallel::ForkManager. Он имеет способ return data to parent, поэтому ребенок может сообщить об ошибке. Затем его метод run_on_finish
может проверять каждую партию для такого флага (отказа) и устанавливать переменную, которая управляет форсированием.
use warnings;
use strict;
use Parallel::ForkManager;
my $pm = new Parallel::ForkManager(2); # only 2 for a managable demo
my $stop_forking;
# The sub gets 6 parameters, but only first (pid) is always defined
# The last one is what a child process may have passed
$pm->run_on_finish(
sub { $stop_forking = 1 if defined $_[-1] }
);
for my $i (0..9)
{
last if $stop_forking;
$pm->start and next; # forks
my $ret = run_job($i); # child process
# Pass data to parent under a condition
if ($ret eq 'FAIL') { $pm->finish(0, \$ret) } # child exits
else { $pm->finish }
}
$pm->wait_all_children;
sub run_job {
my ($i) = $_[0];
sleep 2;
print "Child: job $i exiting\n";
return ($i == 3 ? 'FAIL' : 1);
}
Это останавливает разветвление после серии работ, в течение которого $i == 3
. Добавьте отпечатки для диагностики.
Комментарии. «Обратный вызов» run_on_finish
при его запуске запускается только после завершения целой серии. & lowast;анонимный подканал в нем всегда принимает 6 аргументов, но всегда определяется только первый, дочерний pid. У последнего есть данные, которые могут быть переданы дочерним, и когда это произойдет, мы устанавливаем флаг. Ребенок может возвращать данные, передавая скалярную ссылку на метод finish
. Чтобы указать только условие, мы можем просто передать что-либо. Я использую \$ret
в качестве примера передачи фактических данных.
Подробнее см. Документацию, но это делает то, что вам нужно.
Если вы хотите, чтобы раскошелиться, как и вы, я первый положил в небольшой sleep
там, так что вы не бомбардируют сервер слишком большим числом запросов. Ваши дети могут разговаривать с родителями, используя socketpair. Неисправный ребенок может писать, а остальные могут просто закрыть свой сокет. Родитель продолжает проверять, например, с can_read
от IO::Select. Пример: perlipc. Поскольку вам нужны только дети, чтобы написать родителям, достаточно было и pipe.
Вы также можете сделать это с помощью сигнала. Ребенок, который не отправляет (скажем) SIGUSR1
родительскому объекту, который родительский ловушки и устанавливает глобальную переменную, которая контролирует дальнейшие вилки. Это проще, так как родительский ловушки только один сигнал и не заботятся о том, откуда он. См. perlipc и sigtrap прагма.
Вы также можете использовать файл, как и вы, который, вероятно, прост, так как здесь вас не волнуют проблемы с гонкой (независимо от того, записывают ли дети перекрытие), но только о том, что появляется пустой файл.
Однако во всех этих случаях вы также хотите ограничить количество параллельных процессов.
Наконец, существует ряд модулей, которые могут помочь с этим, например IPC::Run.
& lowast; Чтобы запустить обратный вызов, так как каждый ребенок выходит из системы reap_finished_children
. См. this post.
спасибо за информацию, я сделаю некоторые исследования. Я не знаю, сколько файлов есть для определенного потока, поэтому прямо сейчас я иду, пока wget не сработает. но вы правы, я должен учитывать сервер и не бомбардировать его. последний, который я запустил, составил более 357 фрагментов видео. он действительно загружал очень быстро, хотя. – genx1mx6
@ genx1mx6 Надеюсь, это поможет, даже если в нем в основном перечислены подходы. Я планирую добавить код с 'P :: FM' (сейчас уже поздно). Родитель просто запускается через цикл, чтобы те 357 были созданы сразу, и вы, вероятно, попали на сервер со всем этим сразу с места в карьер. Там, должно быть, было еще больше, так как для родителя нет времени, чтобы вернуться в следующую итерацию, показывая еще одну, поэтому она просто продолжает вращать их. Даже в случае сбоя, вероятно, существует целая группа, пытающаяся загрузить другие несуществующие файлы. Btw, файл, который вы используете, в порядке, но вам нужно ограничить число. – zdim
@ genx1mx6 Я добавил рабочий пример с 'Parallel :: ForkManager'. Я могу добавить код для других методов, но дайте мне знать, как это происходит. – zdim