Perl:子线程中变量$^T的值

Perl: the value of variable $^T in child threads

$^T 存储 perl 程序的开始时间,以秒为单位,自纪元以来。 因为我需要知道一个子线程花费了多少秒,所以问题是: 子线程中的 $^T 是​​否存储自身的开始时间?或者只是从它的母线程中复制值?

运行这个:

#!/usr/bin/env perl
use strict;
use warnings;


sub test_th {
    print $^T,"\n";
}

print $^T."\n"
sleep 10;
my $thr = threads -> create ( \&test_th ); 
$thr -> join;

打印相同的值两次。

正如预期的那样,因为当您线程化时,您实际上继承了所有父变量。

如果您通过分叉尝试此操作:

 #!/usr/bin/env perl

use strict;
use warnings;

use Parallel::ForkManager;

print $^T, "\n";

for ( 1 .. 2 ) {
    sleep 10;
    $mgr->start and next;
    print $^T, "\n";
    $mgr->finish;
}

$mgr->wait_all_children;

尽管分叉 'start' 晚了 10 秒,但您得到了相同的值。

所以回答你的问题 - 不,$^T 在程序实例化时启动。如果您想测量线程 运行 次之类的东西,则必须找到其他方法。

虽然,鉴于 "elapsed time" 充其量只是一个非常粗略的指标(处理器执行诸如调度之类的事情,因此 'real time' 和 'run time' 并没有特别相关)

但也许在每个线程的开始和结束时调用 time() 可以满足您的需求?或者像 Devel::NYTProf 这样的东西?

快速测试会发现 $^T 是在进程启动时为填充定义的,而不是在线程启动时定义的

但是没有什么能阻止您注意线程何时开始。您甚至可以将时间戳保存在 $^T 中,因为它是一个线程变量!

use feature qw( say );
use threads;

sub thread {
   my ($n) = @_;
   sleep $n;
}

sub wrapper {
   my ($n) = @_;
   $^T = time;
   thread($n);
   say sprintf "Thread %s ran for %s seconds.", threads->tid, time-$^T;
}

async { wrapper(5) };
sleep 2;
async { wrapper(2) };
$_->join for threads->list;

输出:

Thread 2 ran for 2 seconds.
Thread 1 ran for 5 seconds.

请注意,分配给 $^T 会将存储的值强制转换为整数,因此它不适合存储 Time::HiRes::time() 的结果。