如何获得 perl 系统调用的 CPU 时间?
How can I get the CPU time for a perl system call?
我有一个使用 system()
调用外部可执行文件的 perl 脚本。我想测量这些外部程序所用的 CPU 秒。理想情况下,我想 运行 使用 shell 内置 time
命令(这是在 Linux 系统上)。像这样:
system("time /path/to/command")
现在,time
将其输出打印到 stderr,但为了这样做,启动在单独的子 shell 中给出的命令。这意味着为了在 shell 中手动 运行ning 时捕获时间输出,您需要显式使用 subshell 并重定向 subshell 的标准错误:
$ time ( command > command.log 2> command.er) 2> time.out
文件 time.out
将具有 time
命令的输出,而 command.er
具有 command
的标准错误。不幸的是,括号破坏了 perl 的系统调用:
$ time ( ls ) 2> er ## works
$ perl -e 'system("time (ls)")'
sh: 1: Syntax error: word unexpected (expecting ")")
这意味着我无法捕获 time
的输出。更糟糕的是,这似乎与版本有关:
$ perl --version | head -n2
This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
但是如果我用更新的版本尝试同样的事情:
$ perl --version | head -n2
This is perl 5, version 24, subversion 1 (v5.24.1) built for x86_64-linux-thread-multi
$ perl -e 'system("time (ls)")'
file1
real 0m0.002s
user 0m0.000s
sys 0m0.000s
不幸的是,我需要在生产机器上 运行 使用它,因此无法升级 Perl。那么,我如何在 Perl 5.18 中为系统调用计时?我需要 user
和 sys
值,因此简单地记录开始和结束时间无济于事。如果有必要,我愿意使用专用模块,尽管我更喜欢让我使用 shell 的 time
的技巧。
更新:事实证明行为上的差异不是因为较新的 perl 版本,而是因为我在 /bin/sh
是 bash
而其他命令在 Ubuntu 系统上被 运行 其 /bin/sh
是 dash
,最小的 shell 不支持 subshells 的括号.
您可以使用 Capture::Tiny 捕获 Perl 中几乎所有内容的 STDOUT 和 STDERR。
use Capture::Tiny 'capture';
my ($stdout, $stderr, $exit) = capture { system "time ls" };
print $stderr;
出于某种原因,输出在我的系统上缺少一些空格,但足够清晰,可以解析出您需要的内容。
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 2272maxresident)k
0inputs+8outputs (0major+111minor)pagefaults 0swaps
您已使用 bash
测试了该命令,但您已将其传递给 sh
。
system("time (ls)")
是
的缩写
system("/bin/sh", "-c", "time (ls)")
但你想要
system("/bin/bash", "-c", "time (ls)")
$ time ( ls ) 2> er ## works
$ perl -e 'system("time (ls)")'
sh: 1: Syntax error: word unexpected (expecting ")")
问题是,在第一种情况下,您的 shell 可能是 /bin/bash
,而在第二种情况下,它是 /bin/sh
。如果你想 运行 你的命令与另一个 shell,你可以使用 system LIST
形式:
system("/bin/bash", "-c", "time(ls)")
注意 1:有 PERL5SHELL
environmnet 值,但这似乎 仅 在 Win32 上生效。
注2:如果你想测量子进程的CPU时间,你可以使用Unix::Getrusage or BSD::Resource模块。
我有一个使用 system()
调用外部可执行文件的 perl 脚本。我想测量这些外部程序所用的 CPU 秒。理想情况下,我想 运行 使用 shell 内置 time
命令(这是在 Linux 系统上)。像这样:
system("time /path/to/command")
现在,time
将其输出打印到 stderr,但为了这样做,启动在单独的子 shell 中给出的命令。这意味着为了在 shell 中手动 运行ning 时捕获时间输出,您需要显式使用 subshell 并重定向 subshell 的标准错误:
$ time ( command > command.log 2> command.er) 2> time.out
文件 time.out
将具有 time
命令的输出,而 command.er
具有 command
的标准错误。不幸的是,括号破坏了 perl 的系统调用:
$ time ( ls ) 2> er ## works
$ perl -e 'system("time (ls)")'
sh: 1: Syntax error: word unexpected (expecting ")")
这意味着我无法捕获 time
的输出。更糟糕的是,这似乎与版本有关:
$ perl --version | head -n2
This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
但是如果我用更新的版本尝试同样的事情:
$ perl --version | head -n2
This is perl 5, version 24, subversion 1 (v5.24.1) built for x86_64-linux-thread-multi
$ perl -e 'system("time (ls)")'
file1
real 0m0.002s
user 0m0.000s
sys 0m0.000s
不幸的是,我需要在生产机器上 运行 使用它,因此无法升级 Perl。那么,我如何在 Perl 5.18 中为系统调用计时?我需要 user
和 sys
值,因此简单地记录开始和结束时间无济于事。如果有必要,我愿意使用专用模块,尽管我更喜欢让我使用 shell 的 time
的技巧。
更新:事实证明行为上的差异不是因为较新的 perl 版本,而是因为我在 /bin/sh
是 bash
而其他命令在 Ubuntu 系统上被 运行 其 /bin/sh
是 dash
,最小的 shell 不支持 subshells 的括号.
您可以使用 Capture::Tiny 捕获 Perl 中几乎所有内容的 STDOUT 和 STDERR。
use Capture::Tiny 'capture';
my ($stdout, $stderr, $exit) = capture { system "time ls" };
print $stderr;
出于某种原因,输出在我的系统上缺少一些空格,但足够清晰,可以解析出您需要的内容。
0.00user 0.00system 0:00.00elapsed 0%CPU (0avgtext+0avgdata 2272maxresident)k
0inputs+8outputs (0major+111minor)pagefaults 0swaps
您已使用 bash
测试了该命令,但您已将其传递给 sh
。
system("time (ls)")
是
的缩写system("/bin/sh", "-c", "time (ls)")
但你想要
system("/bin/bash", "-c", "time (ls)")
$ time ( ls ) 2> er ## works
$ perl -e 'system("time (ls)")'
sh: 1: Syntax error: word unexpected (expecting ")")
问题是,在第一种情况下,您的 shell 可能是 /bin/bash
,而在第二种情况下,它是 /bin/sh
。如果你想 运行 你的命令与另一个 shell,你可以使用 system LIST
形式:
system("/bin/bash", "-c", "time(ls)")
注意 1:有 PERL5SHELL
environmnet 值,但这似乎 仅 在 Win32 上生效。
注2:如果你想测量子进程的CPU时间,你可以使用Unix::Getrusage or BSD::Resource模块。