通过perl“open”测量程序的运行时间

时间:2017-03-28 21:57:39

标签: perl

我正在开发一个带有测试套件的库,该套件使用Perl open来运行它的测试。它看起来像这样:

open (MYOUT, "$myprog $arg1 $arg2 $arg3 2>&1 |") die "Bad stuff happened";

我真正想做的是衡量$myprog的运行时间。不幸的是,只需抓住open命令的开始时间和结束时间,就可以大致掌握启动过程所需的时间。

是否有某种方法可以强制open命令完成整个过程(因此可以准确地测量时间),或者是否有其他方法可以完成同样的事情?

关键限制是我们需要捕获(可能很多)STDOUTSTDERR

1 个答案:

答案 0 :(得分:2)

由于您打开了一个管道,您需要在open之前的时间至少在阅读之后

use warnings;
use strict;
use Time::HiRes qw(gettimeofday tv_interval sleep);

my $t0 = [gettimeofday];

open my $read, '-|', qw(ls -l) or die "Can't open process: $!";

while (<$read>)
{
    sleep 0.1;
    print;
}

print "It took ", tv_interval($t0), " seconds\n";
# close pipe and check 

或者,为了计算整个过程,在管道上调用close之后( 完成所有阅读后)

my $t0 = [gettimeofday];
open my $read, '-|', qw(ls -l)  or die "Can't open process: $!";
# ... while ($read) { ... }
close $read  or 
    warn $! ? "Error closing pipe: $!" : "Exit status: $?";
print "It took ", tv_interval($t0), " seconds\n";

close阻止并等待程序完成

  

关闭管道还会等待管道上执行的进程退出 - 如果您希望之后查看管道的输出 - 并隐式将该命令的退出状态值放入$? [...]

状态检查请参阅$? variable in perlvarsystem

如果定时程序以阻塞的方式分叉并且不对其子女进行wait,则不会正确计时。 在这种情况下,您需要识别他们使用的资源(文件?)并监控它。

我想补充一点,外部命令应该小心放在一起,以避免shell注入问题。一个好的模块是String::ShellQuote。例如,请参阅this answerthis answer

使用模块捕获流可以让您从shell中解脱出来,并可能打开其他方式来运行并更可靠地计时。一个好的是Capture::Tiny(还有其他的)。

感谢HåkonHægland的评论。感谢ikegami让我直截了当,使用close(而不是waitpid)。