7

我注意到,当我运行我的程序perl -MDevel::Cover=-silent,-nogcov foo.pl以收集覆盖率信息foo.pl时,我的程序部分会大幅减速,这些部分会派生和执行非 perl 程序,如tar,gzipdpkg-deb. 感谢这个问题,我想出了如何选择性地禁用 Devel::Cover,所以我现在正在写:

my $is_covering = !!(eval 'Devel::Cover::get_coverage()');
my $pid = fork();
if ($pid == 0) {
    eval 'Devel::Cover::set_coverage("none")' if $is_covering;
    exec 'tar', '-cf', ...
}

这样做,每次测试减少了 5 分钟的运行时间,对于 122 次测试,我节省了 10 小时的计算时间。

不幸的是,我不能总是将此 eval 语句添加到分叉的子进程中。例如,当我使用system(). 我想避免将我的每个system()调用都重写为手册fork/exec

有没有办法为我的分叉进程或基本上不是我的脚本的所有内容禁用 Devel::Cover foo.pl

谢谢!

4

2 回答 2

1

Forks::Super有点重,但它具有在每个 fork 之后但在执行子进程中的任何其他代码之前执行的 post-fork 回调的功能。

use Forks::Super;
my $is_covering = !!(eval 'Devel::Cover::get_coverage()');
POSTFORK_CHILD {
    # runs in every child process immediately after fork()
    eval 'Devel::Cover::set_coverage("none")' if $is_covering;
};
...
于 2020-01-07T18:12:21.563 回答
1

我怀疑您的问题不是分叉本身,而是执行程序。差异在一定程度上是学术性的,但可能会导致可能的解决方案。如果您不介意编译自己的 Devel::Cover 版本,可以尝试注释掉这一行:https ://github.com/pjcj/Devel--Cover/blob/05392f3062dd2bdbf019d9a8fbae1b152b97d862/Cover.xs#L1140

这将导致在exec调用之前收集的任何覆盖数据丢失并加速 exec 调用。

如果您无法编译自己的版本,local *Devel::Cover::_report = sub { };在 exec 调用之前添加也应该加快 exec 的速度,但这最终与您已经拥有的解决方案类似,但缺点是不使用已发布的 API。

于 2020-01-09T20:13:47.997 回答