Reputation: 53231
Note: I've seen https://stackoverflow.com/a/64315882/21728 and understand that time
is not necessarily that precise. However, I'm seeing a 4× difference between the reported time
and time it actually took, and I'd like to understand what's causing it on macOS – that's the point of this question.
I'm trying to compare two ways to run a binary and they report very similar time
info:
$ time ../../../node_modules/.bin/quicktype --version
quicktype version 15.0.214
Visit quicktype.io for more info.
../../../node_modules/.bin/quicktype --version 0.46s user 0.06s system 110% cpu 0.474 total
$ time $(yarn bin quicktype) --version
quicktype version 15.0.214
Visit quicktype.io for more info.
$(yarn bin quicktype) --version 0.44s user 0.06s system 110% cpu 0.449 total
However, the latter feels much slower. So I've added timestamps before and after:
$ date +"%T.%3N" && time $(yarn bin quicktype) --version && date +"%T.%3N"
15:11:09.667
quicktype version 15.0.214
Visit quicktype.io for more info.
$(yarn bin quicktype) --version 0.49s user 0.06s system 108% cpu 0.513 total
15:11:11.400
Indeed, the difference between 15:11:09.667
and 15:11:11.400
is almost two seconds but time
is reporting about 0.5 second. What explains this rather vast difference?
Upvotes: 0
Views: 680
Reputation: 57942
Generally speaking, for an external command cmd
, it is the case that shell expansions are done by the shell before cmd
is started. This includes command substitution cmd $(other_cmd)
, globbing cmd *.txt
, variable expansion cmd $FOO
, and so forth. So cmd
is executed with the result of the expansion as its arguments, and never sees the original command line typed by the user.
Thus if time
were an ordinary external command, as it is if you use /usr/bin/time
, then the command yarn bin quicktype
would be run before time
even starts, and it would be just as if you had run time .../quicktype --version
. It only measures the time taken to execute .../quicktype --version
, and it would not (and could not) account for the time taken for the shell to generate that command line by running yarn
.
Now the situation here is not quite that simple because time
is actually a builtin command in many shells, and not an external command. So it doesn't necessarily have to follow the above behavior. However, in my tests, zsh
's builtin time
behaves the same, and does not count the time taken to run the substituted command yarn
. On the other hand, in bash
, the time
builtin does include it.
As you saw, you can circumvent the issue by timing the running of a new shell which does both the command substitution (running yarn
) and the resulting ../quicktype
command itself. Then you will definitely include the time taken by both steps.
Upvotes: 1
Reputation: 53231
I was using the time
wrong.
First, time
is different from /usr/bin/time
on my Mac:
time
is a shell built-in (I use Zsh)/usr/bin/time
is BSD timeThis gives the expected results:
$ /usr/bin/time bash -c '../../../node_modules/.bin/quicktype --version'
quicktype version 15.0.214
Visit quicktype.io for more info.
0.49 real 0.47 user 0.06 sys
$ /usr/bin/time bash -c '$(yarn bin quicktype) --version'
quicktype version 15.0.214
Visit quicktype.io for more info.
2.02 real 1.92 user 0.27 sys
Upvotes: 2