times#
Report CPU time consumed by this process and its terminated children.
times asks the kernel how many seconds of user-mode and kernel-mode
CPU have been charged to the current process, and — separately — to
children that have already been reaped. The return is four floating-
point seconds: user, system, child-user, child-system. It answers
“how much CPU have I burned?”, not “how much wall-clock time has
passed?” — for that, see time.
Synopsis#
my ($user, $system, $cuser, $csystem) = times;
my $user_only = times; # scalar context
What you get back#
In list context, four values:
$user— CPU time spent in user-mode code of this process.$system— CPU time spent in the kernel on behalf of this process.$cuser— user-mode CPU time of terminated child processes.$csystem— kernel-mode CPU time of terminated child processes.
All four are seconds as double-precision floats; resolution is
microsecond on Linux (sourced from getrusage).
In scalar context, times returns just $user.
times takes no arguments and cannot fail in a way visible to the
caller.
Children’s times — the “terminated” rule#
$cuser and $csystem aggregate CPU only from children that have
been reaped — i.e. a wait or waitpid has
successfully collected their exit status, or they were autoreaped
because $SIG{CHLD} was set to 'IGNORE'. A child that is still
running, or has exited but not yet been reaped (a zombie), contributes
nothing.
This matters when measuring a pipeline that spawns workers:
my $pid = fork;
if ($pid == 0) { do_work(); exit }
# (busy child runs here)
my ($u0, $s0, $cu0, $cs0) = times; # $cu0, $cs0 still 0
waitpid($pid, 0);
my ($u1, $s1, $cu1, $cs1) = times; # now $cu1, $cs1 reflect child
Until the waitpid returns, the child’s CPU does not appear in the
parent’s times.
Examples#
Measure CPU cost of a block of work, excluding wall-clock sleeps or I/O waits:
my ($u0, $s0) = times;
compute_heavy();
my ($u1, $s1) = times;
printf "compute used %.3f s user + %.3f s system\n",
$u1 - $u0, $s1 - $s0;
Compare CPU time to wall-clock time — a low ratio means the process was mostly waiting rather than computing:
use Time::HiRes qw(time);
my $t0 = time;
my ($u0, $s0) = times;
do_mixed_io_and_compute();
my $wall = time - $t0;
my ($u1, $s1) = times;
printf "cpu/wall = %.2f\n", ($u1 - $u0 + $s1 - $s0) / $wall;
Attribute a parallel workload to its children. Reap every child
before reading times:
my @pids = map { my $p = fork; $p == 0 ? (worker($_), exit) : $p } 1..4;
waitpid($_, 0) for @pids;
my (undef, undef, $cu, $cs) = times;
printf "workers used %.2f s user + %.2f s system\n", $cu, $cs;
Scalar context when only the user time matters — e.g. a quick self-profiling print:
printf STDERR "[%.2f] reached checkpoint\n", scalar times;
Edge cases#
No arguments, no prototype to worry about.
timesis a zero-argument built-in;times()andtimesparse identically. It is not the transliteration operator — that istr///(aliasy///), which is a separate token.Scalar vs list context is load-bearing. Writing
my $t = times;binds$userto$t, discarding the other three values silently. Usemy ($u,$s,$cu,$cs) = times;when you want them all.Unreaped children don’t count. See the “terminated” rule above. Reading
timesbeforewaitgives$cuser == $csystem == 0even when the child is visibly burning CPU intop.Threads do count. On Linux, kernel-threaded work in the current process shows up in
$user/$systemjust like single-threaded work. Threads in a separate process don’t, until that process exits and is reaped.Clock is monotonic-within-process, not wall-clock.
timesnever goes backwards across a single process’s lifetime, but successivetimescalls are not directly comparable between parent and child — eachgetrusageaccounting is local.Resolution. Linux reports microsecond-resolution ticks via
getrusage, so short measurements (sub-millisecond) are noisy but not zero. For high-precision wall-clock timing, useTime::HiRes::time, nottimes.Overflow. Values are floats; they can in principle lose sub-microsecond precision after very long runs (years of CPU), but this is not a concern for normal programs.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
time— wall-clock seconds since the epoch; use it when you want elapsed real time, not CPU timeTime::HiRes::time— high-resolution wall-clock time, the usual partner for CPU accountingPOSIX::times— POSIX wrapper returning an additional real-time “clock ticks since boot” value; use it when you need the elapsed field the built-in omitswait— reap a child so its CPU starts counting in$cuser/$csystemwaitpid— reap a specific child for the same reason, without blocking on unrelated onesfork— the operation whose cost shows up in the child columns once the child is reaped