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:
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