0

I'm using time to measure execution speed of a program. However, it is too fast, so I need more decimal precision.

From man time, I understand I can specify fields like %U and %S for user or system time, but I don't see how I can apply sprint format options to control things like the number of decimals.

I see

$ time -f "%S" ./main
0.00

And I would rather see:

$ time -f "%S<something???05>" ./main
0.000015

Update

$ type time
time is a shell keyword
$ bash --version
bash --version
GNU bash, version 5.0.16(1)-release (x86_64-pc-linux-gnu)
Mittenchops
  • 18,633
  • 33
  • 128
  • 246
  • Add output of `type time` and your bash version to your question. – Cyrus May 16 '20 at 15:14
  • `man time` is the wrong document to read. It covers the OS-provided time command, not the bash-builtin one. (Bash doesn't even consider `time` a built-in command; it's a *keyword* that can be provided at the start of a pipeline -- see https://www.gnu.org/software/bash/manual/html_node/Pipelines.html#index-time, and the specification of TIMEFORMAT in https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html#Bash-Variables). – Charles Duffy May 16 '20 at 15:30
  • Also, don't use `bash --version`; it tells which version of bash is *first in your PATH*, not which version is *currently running* -- if you're, say, on MacOS and installed bash 5 with macports/homebrew/etc., it's very common to be running a version that's older than what's first in your PATH. Instead, `echo "$BASH_VERSION"`. – Charles Duffy May 16 '20 at 15:32
  • That said, more than three decimal points is generally pretty useless, because anything that might otherwise be useful information about your program's performance will be lost in the noise of new processes getting forked, shared libraries linked/loaded, etc. If you want fine-grained performance numbers regarding a program written in C, [`cachegrind`](https://valgrind.org/docs/manual/cg-manual.html) and its frontend [KCacheGrind](https://kcachegrind.github.io/html/Home.html) are your friends -- or just [`gprof`](https://sourceware.org/binutils/docs/gprof/) for something low-rent. – Charles Duffy May 16 '20 at 15:38
  • ...whereas if you want to do a bunch of trials that factor out load time, build a test harness does all your initial-state setup only once and starts the clock only immediately before the algorithm you care about (potentially after forking a copy of that original process, if you want to run forward from the same starting state more than once). – Charles Duffy May 16 '20 at 15:41
  • One can of course also just time 100 or 1000 runs and divide to get an average. That does a lot of good to factor out the noise as well. – Charles Duffy May 16 '20 at 15:45

2 Answers2

2

Bash has a built-in time command which is used in your case.

The time described in man time (usually installed under /usr/bin/time) can be called as follows

command time -f "%S" ./main

it is too fast, so I need more decimal precision. I would rather see: 0.000015

Neither bash's time nor GNU time seem to be able to output times with such high precision. And if you really think about it there is no need to. There is always background noise and starting a process takes time too. If you measure such short time intervals you mostly measure anything but the time your program actually takes.

If you really have to, you could measure the wall clock time in bash 5 ✱:

t=$EPOCHREALTIME
./main
t="$EPOCHREALTIME - $t" # measure time before starting bc
bc <<< "$t"

However, it would be better to do this directly inside your program. If you could repeat your actual program 1000 times there and measure the complete time you would get a somewhat usable measurement.

✱ On my system measuring with bash added around 0.000008 s of overhead. The overhead was measured with

$ for i in {1..10000}; do t=$EPOCHREALTIME; t="$EPOCHREALTIME - $t"; bc <<< "$t"; done | sponge | datamash min 1 median 1 max 1
4e-06   8e-06   8.1e-05
Socowi
  • 25,550
  • 3
  • 32
  • 54
2

Bash only supports only three digits after the decimal point in the built-in time's output (this implementation of time is not the one documented in man time, but is instead the one documented in the Pipelines page in the bash manual).

From the documentation on TIMEFORMAT:

The optional p is a digit specifying the precision, the number of fractional digits after a decimal point. A value of 0 causes no decimal point or fraction to be output. At most three places after the decimal point may be specified; values of p greater than 3 are changed to 3. If p is not specified, the value 3 is used.

Thus, to get that maximum:

TIMEFORMAT=%3lR time ./main
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441