logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git
commit: c5bcb7d2aec67109b975fb708cdf4ae4bd1c30bd
parent 47b057e876d1034b3dcd40626a3280e49a52ff92
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Thu, 26 Sep 2024 15:39:17 +0200

cmd/time: add support for -v option

Also switched -p to getrusage as well since it allows much
greater precision (rough ~millisecond vs. exact microsecond).

Diffstat:

Mcmd/time.111++++++++---
Mcmd/time.c71+++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mtest-cmd/time.t4++--
3 files changed, 67 insertions(+), 19 deletions(-)

diff --git a/cmd/time.1 b/cmd/time.1 @@ -9,7 +9,7 @@ .Nd measure time used by a command .Sh SYNOPSIS .Nm -.Op Fl p +.Op Fl p Ns | Ns Fl v .Ar command .Op Ar argument... .Sh DESCRIPTION @@ -18,8 +18,12 @@ measures the wall-clock time, user CPU time, system/kernel CPU time, used by .Ar command and outputs it to stderr. .Sh OPTIONS -.Fl p -is ignored for compatibility reasons, the output is always in the POSIX format. +.Bl -tag -width _p +.It Fl p +(default) Output in POSIX format. +.It Fl v +Detailed output. +.El .Sh EXIT STATUS If .Ar command @@ -38,6 +42,7 @@ was found but couldn't be invoked could not be found .El .Sh SEE ALSO +.Xr getrusage 3 , .Xr times 3 .Sh STANDARDS .Nm diff --git a/cmd/time.c b/cmd/time.c @@ -3,18 +3,25 @@ // SPDX-License-Identifier: MPL-2.0 #define _POSIX_C_SOURCE 200809L -#include <errno.h> // errno -#include <stdio.h> // perror, fprintf -#include <stdlib.h> // abort -#include <string.h> // strerror -#include <sys/times.h> // times -#include <sys/wait.h> // waitpid -#include <unistd.h> // sysconf, fork, execvp, getopt +#include <errno.h> // errno +#include <stdio.h> // perror, fprintf +#include <stdlib.h> // abort +#include <string.h> // strerror +#include <sys/resource.h> // getrusage +#include <sys/times.h> // times +#include <sys/wait.h> // waitpid +#include <unistd.h> // sysconf, fork, execvp, getopt + +enum cmd_time_mode +{ + CMD_TIME_POSIX = 0, + CMD_TIME_VERBOSE = 1, +}; static void usage(void) { - fprintf(stderr, "Usage: time command [argument ...]\n"); + fprintf(stderr, "Usage: time [-p|-v] command [argument ...]\n"); } int @@ -22,6 +29,7 @@ main(int argc, char *argv[]) { struct tms tms; int ret = 0; + enum cmd_time_mode mode = CMD_TIME_POSIX; if(argc <= 1) { @@ -30,11 +38,15 @@ main(int argc, char *argv[]) } int c = -1; - while((c = getopt(argc, argv, ":p")) != -1) + while((c = getopt(argc, argv, ":pv")) != -1) { switch(c) { case 'p': // POSIX format (default) + mode = CMD_TIME_POSIX; + break; + case 'v': + mode = CMD_TIME_VERBOSE; break; case ':': fprintf(stderr, "time: error: Missing operand for option: '-%c'\n", optopt); @@ -97,11 +109,42 @@ main(int argc, char *argv[]) ret = 128 + WTERMSIG(status); } - fprintf(stderr, - "real %f\nuser %f\nsys %f\n", - (t1 - t0) / (double)ticks, - tms.tms_cutime / (double)ticks, - tms.tms_cstime / (double)ticks); + struct rusage usage; + if(getrusage(RUSAGE_CHILDREN, &usage) != 0) + { + fprintf( + stderr, "time: error: Failed getting resource usage of childrens: %s\n", strerror(errno)); + return 1; + } + + double utime_s = usage.ru_utime.tv_sec + (usage.ru_utime.tv_usec * 0.000001); + double stime_s = usage.ru_stime.tv_sec + (usage.ru_stime.tv_usec * 0.000001); + + switch(mode) + { + case CMD_TIME_POSIX: + fprintf(stderr, "real %f\nuser %f\nsys %f\n", (t1 - t0) / (double)ticks, utime_s, stime_s); + break; + case CMD_TIME_VERBOSE: + fprintf(stderr, "\tExecutable: %s\n", argv[0]); + fprintf(stderr, "\tReal time: %06f\n", (t1 - t0) / (double)ticks); + fprintf(stderr, "\tUser time: %06f\n", utime_s); + fprintf(stderr, "\tSystem time: %06f\n", stime_s); +#ifdef __linux__ + fprintf(stderr, "\tMaximum resident set size (maxrss): %ld kB\n", usage.ru_maxrss); + fprintf(stderr, "\tMinor (no I/O required) page faults (minflt): %ld\n", usage.ru_minflt); + fprintf(stderr, "\tMajor (I/O required) page faults (majflt): %ld\n", usage.ru_majflt); + fprintf(stderr, "\tMajor (I/O required) page faults (majflt): %ld\n", usage.ru_majflt); + fprintf(stderr, "\tVoluntary context switch (nvcsw): %ld\n", usage.ru_nvcsw); + fprintf(stderr, "\tInvoluntary context switch (nivcsw): %ld\n", usage.ru_nivcsw); +#endif + + if(WIFEXITED(status)) fprintf(stderr, "\tExit status: %d\n", WEXITSTATUS(status)); + + break; + default: + abort(); + } if(WIFEXITED(status)) { diff --git a/test-cmd/time.t b/test-cmd/time.t @@ -5,11 +5,11 @@ $ cd $TESTDIR/../cmd $ ./time - Usage: time command [argument ...] + Usage: time [-p|-v] command [argument ...] $ ./time -f time: error: Unrecognised option: '-f' - Usage: time command [argument ...] + Usage: time [-p|-v] command [argument ...] [1] $ ./time /var/empty/e/no/ent