我根据Perl脚本多次迭代的标准进行了大量的文件搜索,似乎占用了100%的CPU时间。有没有办法控制我的脚本CPU利用率?我读到了一些关于在我的脚本中放入空睡眠周期的地方。但我不知道该怎么做。
答案 0 :(得分:10)
您可以降低操作系统指定的流程(Perl)优先级:windows或linux
最低优先级的示例:
windows
start /LOW perl <myscript>
linux
nice +19 perl <myscript>
答案 1 :(得分:7)
提高CPU利用率的一个好方法是使用更好的算法。不要猜测代码在哪里花费所有时间:使用分析器。 Devel::NYTProf
是一个很棒的工具。
请务必记住Amdahl's law。例如,假设您的程序的一部分使用二次算法,并且您可以使用线性算法替换它。万岁!但是,如果所讨论的代码仅占总运行时间的5%,那么您最英勇的努力不会带来微不足道的5%改进。使用分析器确定在其他地方是否有更高速度的机会。
您没有告诉我们您要搜索的内容,即使是最知名的算法也可能是CPU密集型的。考虑到您的操作系统的调度程序已经过编写,手动调整,测试和重写,以便有效地使用系统资源。是的,有些任务需要专门的调度程序,但是这种情况很少见 - 甚至不太可能,因为你使用的是Perl。
不要将其视为代码占用CPU的一个坏迹象。您可能会惊讶地发现,性能至关重要的实时系统中最难的挑战之一就是让CPU保持忙碌而不是闲置。
答案 2 :(得分:5)
您可以使用sleep or usleep。您可以做的另一件事是降低流程优先级。
更新: 见setpriority()
答案 3 :(得分:3)
睡觉:
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.
}
}
答案 4 :(得分:2)
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;
}
(未经测试......)在整个代码中调用足够relax
个调用,这应该平均到CPU时间接近或低于50%。
BSD::Resource可以更少侵入性地执行此操作,您也可以抓取Time::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
秒的CPU时间向您发出信号,此时您将重置计数器并进入睡眠状态。这不应该要求对代码的其余部分进行任何更改。
答案 5 :(得分:2)
你的剧本实际上是在做什么吗?例如,如果你计算一个mandelbrot集,你将拥有消耗CPU的循环,但是它们一直在积极处理数据。
或者你有等待更多数据处理的循环:
while(1) {
process_data() if data_ready();
}
在第一种情况下,设置优先级可能是最佳解决方案。它会减慢计算速度,但只能为系统上任何其他进程提供服务所需的速度。
在第二种情况下,您可以通过仅仅几分之一秒的休眠来大幅提高CPU利用率。
while(1) {
process_data() if data_ready();
select( undef, undef, undef, 0.1 );
}
如果您从select
可以操作的来源提取数据,那就更好了。您可以安排循环阻止,直到数据准备就绪。
use IO::Select;
my $s = IO::Select->new($handle);
while(1) {
process_data() if $s->can_read;
}
选择适用于* NIX系统上的套接字和文件句柄。在Windows系统上,您只能选择套接字。