I am preparing some code for a another blog post I came across some very unexpected behavior on my terminal that really got me thinking 🤔. Time was behaving in 2 different ways depending on what it seems an entirely unrelated reason.

Check this output out:
$ time go run github.com/efrag/blog-posts/go_routines/ one-routine-wait ... real 0m1.556s user 0m1.545s sys 0m0.064s
Looks pretty normal right? I run the command prefixed with time
and I got the expected output. But check what happens when I run it like this:
$ GOMAXPROCS=10 time go run github.com/efrag/blog-posts/go_routines/ one-routine-wait ... 1.54user 0.07system 0:01.58elapsed 102%CPU (0avgtext+0avgdata 46812maxresident)k 0inputs+3112outputs (0major+16202minor)pagefaults 0swaps
That looks pretty weird right? Did my terminal suddenly decide that I am an “advanced” user and went all out with a more precise/detailed view of the output for time
? Surely that can’t be the case 🤪 – so what’s going on here?
I decided to strip out all the things and just go with a very plain command to eliminate any doubt. Let’s just use a simple ls
on a directory and run things again:
$ time ls -l ... real 0m0.005s user 0m0.005s sys 0m0.000s
and one more time with:
$ a=1 time ls -l ... 0.00user 0.00system 0:00.00elapsed 75%CPU (0avgtext+0avgdata 3032maxresident)k 0inputs+0outputs (0major+162minor)pagefaults 0swaps
Again same output but now it got me thinking – could this be something related with my terminal instead? Well, kinda. After a lot of looking around and reading the man
pages for both bash
and time
it turns out that there is a logical explanation after all ¯\_(ツ)_/¯.
Clue #1
Bash offers extended functionality to the terminal. When in doubt if something is actually part of bash
or a standard unix command you can do the following:
$ type which which is /usr/bin/which $ type time time is a shell keyword
Turns out when running time
on the terminal I was not using the Unix time
command rather the time
keyword from bash
.
Clue #2
Looking further in the bash
documentation there is a section that talks about pipelines in bash
and the example there demonstrates the use of the keyword time
.
A pipeline is a sequence of one or more commands separated by one of the control operators | or |&. The format for a pipeline is:
[time [-p]] [ ! ] command [ [|⎪|&] command2 … ]…
If the time reserved word precedes a pipeline, the elapsed as well as user and system time consumed by its execution are reported when the pipeline terminates.
Clue #3
The man
page for the unix time
command actually verifies this as well as it says:
Users of the bash shell need to use an explicit path in order to run the external time command and not the shell builtin variant.
OK – so now that we have all of clues what is actually happening with my command? Turns out that the explanation is quite simple. Bash will use the builtin variant when we define a pipeline that starts with the keyword time
which follows the POSIX
standard of reporting the time statistics.
But, when we put anything before the keyword time
then bash will not default to its builtin keyword but rather use the external unix command whose output format is determined as
%Uuser %Ssystem %Eelapsed %PCPU (%Xtext+%Ddata %Mmax)k %Iinputs+%Ooutputs (%Fmajor+%Rminor)pagefaults %Wswaps
which is what I was seeing when defining an env
variable before running my command 🤯.