Я делаю много файла, ищущего на основе критерии в нескольких повторениях из моего сценария Perl, и это, кажется, поднимает 100% процессорного времени. Существует ли способ управлять моей загрузкой ЦП сценария? Я читал где-нибудь о помещении пустых циклов сна в моем сценарии. Но я не уверен, как сделать это.
можно снизить приоритет процесса (Perl's), назначенный операционной системой: windows или linux
пример для самого низкого приоритета:
windows
start /LOW perl <myscript>
linux
nice +19 perl <myscript>
Вы можете использовать для сна или сна . Другое, что вы можете сделать, это снизить приоритет процесса.
Обновить: Смотрите setpripriority()
Просто спать:
while ($not_done_yet) {
do_stuff_here();
sleep 1; # <-- sleep for 1 second.
}
или чуть больше фантазии, делать N операций за цикл сна:
my $op_count = 0;
while ($not_done_yet) {
do_stuff_here();
$op_count ++;
if ($op_count >= 100) {
$op_count = 0;
sleep 1; # <-- sleep for 1 second every 100 loops.
}
}
Отличный способ улучшить использование ЦП - это использовать лучше алгоритмы. Не угадайте, на что ваш код тратит все свое время: используйте профилировщик. Devel :: NYTProf
- отличный инструмент для этого.
Обязательно помните закон Амдала . Например, предположим, что часть вашей программы использует квадратичный алгоритм и, приложив некоторые усилия, вы можете заменить его линейным. Ура! Но если на рассматриваемый код приходится только 5% от общего времени выполнения, ваши самые героические усилия могут принести не больше, чем крошечное пятипроцентное улучшение. Используйте профилировщик, чтобы определить, доступны ли где-либо возможности для большего ускорения.
Вы не говорите нам, что ищете, и даже самые известные алгоритмы могут сильно загружать процессор. Учтите, что планировщик вашей операционной системы был написан, настроен, протестирован и переписан для эффективного использования системных ресурсов. Да, для некоторых задач требуются специализированные планировщики, но такие случаи редки - даже менее вероятно, если вы используете Perl.
Не воспринимайте это как плохой знак того, что ваш код поглощает процессор. Вы можете быть удивлены, узнав, что одна из самых сложных задач в системах реального времени, где производительность имеет решающее значение, - это поддерживать загруженность ЦП, а не бездействие.
Ваш сценарий на самом деле все время что-то делает? Например, если вы вычислить набор мандельброта, то у вас будут циклы, которые потребляют процессор, но активно обрабатывают данные все время.
Или у вас есть циклы, в которых вы ожидаете обработки большего количества данных:
while(1) {
process_data() if data_ready();
}
В первом случае, установка приоритета, вероятно, является лучшим решением. Он замедлит вычисления, но только настолько, насколько это необходимо для обслуживания любых других процессов в системе.
Во втором случае можно значительно повысить загрузку процессора, проспав лишь долю секунды.
while(1) {
process_data() if data_ready();
select( undef, undef, undef, 0.1 );
}
Если вы извлекаете данные из источника, на котором выберите
, то тем лучше. Можно организовать блокировку цикла до тех пор, пока данные не будут готовы.
use IO::Select;
my $s = IO::Select->new($handle);
while(1) {
process_data() if $s->can_read;
}
Выбор работает на сокетах и файловых дескрипторах на системах *NIX. В системах Windows можно выбирать только против сокетов.
сна + время + время может вроде как сделать это.
my $base = time;
my $ratio = 0.5;
my $used = 0;
sub relax {
my $now = time;
my ($total) = times;
return if $now - $base < 10 or $total - $used < 5; # otherwise too imprecise
my $over = ($total - $used) - $ratio * ($now - $base);
$base = $now + ($over > 0 && sleep($over));
$used = $total;
}
(Непроверенные...) Посыпайте достаточно расслабьтесь
вызовов по всему вашему коду, и это должно в среднем составлять около или менее 50% процессорного времени.
BSD::Ресурс может делать это менее инвазивно, и вы можете также захватить Время::HiRes для большей точности.
my $base = clock_gettime(CLOCK_MONOTONIC);
my (undef, $hard) = getrlimit(RLIMIT_CPU);
my $interval = 10;
if ($hard != RLIM_INFINITY && $hard < $interval) {$interval = $hard / 2}
my $ratio = 0.5;
$SIG{XCPU} = sub {
setrlimit(RLIMIT_CPU, $interval, $hard);
my $now = clock_gettime(CLOCK_MONOTONIC);
my $over = $interval - $ratio * ($now - $base);
$base = $now + ($over > 0 && sleep($over));
};
setrlimit(RLIMIT_CPU, $interval, RLIM_INFINITY);
(Также непроверенный...) На системе, которая его поддерживает, это должно просить операционную систему сигнализировать вам каждые $interval
секунд процессорного времени, после чего вы сбрасываете счетчик и спите. Это не должно требовать внесения изменений в остальной код.