Processes and jobs · bash builtin
time
Measure how long a command takes (wall-clock, user and system CPU time); GNU /usr/bin/time also reports memory and I/O.
time [-p] PIPELINE or /usr/bin/time [-v] [-f FORMAT] [-o FILE] COMMAND [ARG...]
There are two different things called time. In bash (and zsh, ksh), time is a shell
keyword: it times the whole pipeline after it, including shell functions, loops and { ...; }
groups, and prints real, user and sys on standard error. Its format is controlled by the
TIMEFORMAT variable. There is also a separate program, GNU time, at /usr/bin/time
(Debian package time), which can only run an external command but reports much more: maximum
resident memory, page faults, context switches and file-system I/O, in a format you choose with
-f, written to a file with -o.
The three numbers: real is elapsed wall-clock time; user is CPU time spent in the program's
own code; sys is CPU time spent in the kernel on its behalf. A program that waits on the
network or sleep has a large real and tiny user/sys; a multi-threaded program can show
more user than real, because several cores were busy at once.
Typing time cmd at a bash prompt always gets the keyword. To get GNU time, write the full path
/usr/bin/time, or command time / \time, which bypass the keyword. sh (dash) has no
time keyword, so there time runs /usr/bin/time.
Examples
Time a command
time sleep 0.5
real 0m0.502s user 0m0.000s sys 0m0.001s
real is about half a second of elapsed time; user and sys are near zero because
sleep waits without using the CPU. The report goes to standard error, after the command's
own output.
Compare wall-clock and CPU time
time python3 -c 'sum(i * i for i in range(3_000_000))'
real 0m0.164s user 0m0.159s sys 0m0.005s
A CPU-bound command: almost all of real is user time. If real were much larger than
user + sys, the program would be waiting on I/O, the network or other processes.
Check which time you are running
type time
type -a /usr/bin/time
time is a shell keyword /usr/bin/time is /usr/bin/time
In bash, time is a keyword, parsed before the command runs, which is why it can time
pipelines and functions. GNU time is a normal program on disk.
Time a whole pipeline or block
time (sleep 0.2 | sleep 0.3)
time { for i in 1 2 3; do sleep 0.1; done; }
real 0m0.303s user 0m0.000s sys 0m0.005s real 0m0.306s user 0m0.002s sys 0m0.004s
The keyword times everything after it until the end of the pipeline: here a subshell holding a pipeline (0.3 s, the slower stage) and a loop in braces (three 0.1 s sleeps).
Change the output format
TIMEFORMAT='took %3R s (user %3U s, sys %3S s, %P%% CPU)'
time sleep 0.3
took 0.303 s (user 0.000 s, sys 0.003 s, 0.85% CPU)
TIMEFORMAT sets the keyword's report: %R, %U and %S are real, user and sys seconds,
the digit is the number of decimals, %P the CPU percentage. time -p instead gives the
POSIX format, three lines real, user, sys.
Capture the timing in a variable or file
TIMEFORMAT=%R
{ time sleep 0.2 > /dev/null; } 2> elapsed.txt
echo "elapsed: $(cat elapsed.txt) s"
elapsed: 0.203 s
The keyword writes to the shell's standard error, not the command's, so time cmd 2> file
does not capture it. Wrap the timed command in { ...; } and redirect the group.
GNU time's default report
/usr/bin/time sort access.log > /dev/null
0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 1152maxresident)k 12inputs+0outputs (0major+106minor)pagefaults 0swaps
One dense line: user and system seconds, elapsed time, CPU percentage, then memory
(maxresident is peak memory in KiB), file-system inputs and outputs in 512-byte blocks, and
page faults.
Full resource report with -v
/usr/bin/time -v python3 -c 'x = bytearray(80_000_000)' 2>&1 | head -12
Command being timed: "python3 -c x = bytearray(80_000_000)" User time (seconds): 0.01 System time (seconds): 0.05 Percent of CPU this job got: 100% Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.06 Average shared text size (kbytes): 0 Average unshared data size (kbytes): 0 Average stack size (kbytes): 0 Average total size (kbytes): 0 Maximum resident set size (kbytes): 84480 Average resident set size (kbytes): 0 Major (requiring I/O) page faults: 0
-v prints one labeled line per measurement. Maximum resident set size is the figure people
usually want: the peak memory the program used, here about 80 MB plus Python itself. The
output is cut at 12 lines with head; the full report also covers context switches,
file-system I/O and the exit status.
Pick the fields with -f
/usr/bin/time -f '%e s elapsed, %M KiB peak, exit %x' gzip -k -9 access.log
0.00 s elapsed, 768 KiB peak, exit 0
-f takes a format: %e elapsed seconds, %M peak resident memory in KiB, %x the exit
status, %U/%S user and system time, %C the command line. Ideal for logging the cost of
batch jobs.
Write measurements to a file
for f in data/users.csv data/sales.csv; do
/usr/bin/time -a -o times.log -f "%e s %M KiB %C" sort "$f" > /dev/null
done
cat times.log
0.00 s 1152 KiB sort data/users.csv 0.00 s 1152 KiB sort data/sales.csv
-o FILE writes the report to a file instead of standard error, so it does not mix with the
command's own messages, and -a appends instead of overwriting.
The exit status passes through
/usr/bin/time -f '%e s' ls missing.txt
echo "exit status: $?"
ls: cannot access 'missing.txt': No such file or directory Command exited with non-zero status 2 0.00 s exit status: 2
GNU time reports Command exited with non-zero status 2 before its own line and then
exits with the command's status, so it can wrap commands in scripts without hiding failures.
The bash keyword also preserves the status.
GNU time cannot time functions or builtins
build() { sleep 0.1; }
/usr/bin/time -f %e build
echo "exit status: $?"
/usr/bin/time: cannot run build: No such file or directory Command exited with non-zero status 127 0.00 exit status: 127
/usr/bin/time executes a program from PATH, so it does not know the shell function and
fails with status 127. Use the keyword (time build) for functions and pipelines.
Common pitfalls
Expecting
time cmd > out 2> errto put the timing inerr. The bash keyword reports on the shell's standard error; use{ time cmd; } 2> err.Reaching for
/usr/bin/time -von a minimal system where it is not installed (Debian packagetime). The bash keyword is always there, but it does not measure memory.Timing something once and drawing conclusions. Caches, CPU frequency scaling and other load change results; run it several times, or use a benchmarking tool such as
hyperfinefor serious comparisons.Reading
usergreater thanrealas an error. It means the program used several cores in parallel.
GNU vs BSD and macOS
The examples above ran the GNU/Linux version. These are the differences that matter on macOS and the BSDs (written from their documentation, not run here).
macOS
/usr/bin/timeis the BSD version: no-for-v. Use-lfor a resource report including maximum resident set size (in bytes, not KiB) and-pfor POSIX output. GNU time is available from Homebrew asgtime.zsh's
timekeyword prints a different one-line format, controlled byTIMEFMTrather than bash'sTIMEFORMAT.
Options worth knowing
A selection, described in our own words. For the full list, see time(1).
| Option | What it does |
|---|---|
-p, --portability | Use the POSIX output format: real, user and sys on separate lines. |
-v, --verbose | GNU time: print a detailed, labeled resource report. |
-f, --format FORMAT | GNU time: print the report using FORMAT (%e elapsed, %M peak KiB, %x exit status, ...). |
-o, --output FILE | GNU time: write the report to FILE instead of standard error. |
-a, --append | GNU time: with -o, append to FILE instead of overwriting it. |
-q, --quiet | GNU time: do not report abnormal termination or non-zero exit status. |
Related
timeoutRun a command with a time limit, and kill it if it is still running when the time is up.sleepPause for a given amount of time, in seconds by default, with m, h and d suffixes and fractions allowed.niceRun a command with a lower (or, as root, higher) CPU scheduling priority, or print the current niceness.psPrint a snapshot of running processes, with the columns, filters and sort order you choose.datePrint the current date and time in any format, or convert and calculate dates.- RedirectionHow >, >>, 2>, 2>&1, &>, < and exec move a command's input and output between files and file descriptors, and why the order matters.