mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Simplify the rusage.com command
This commit is contained in:
parent
b592716d1c
commit
dcda6f7d8d
7 changed files with 86 additions and 106 deletions
|
@ -7,121 +7,83 @@
|
|||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/math.h"
|
||||
#include "libc/runtime/clktck.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/calls/struct/timespec.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/log/appendresourcereport.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/append.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
#define PREFIX "\e[1mRL\e[0m: "
|
||||
|
||||
static void PrintResourceReport(struct rusage *ru) {
|
||||
long utime, stime;
|
||||
long double ticks;
|
||||
if (ru->ru_maxrss) {
|
||||
fprintf(stderr, "%sballooned to %,ldkb in size\n", PREFIX, ru->ru_maxrss);
|
||||
}
|
||||
if ((utime = ru->ru_utime.tv_sec * 1000000 + ru->ru_utime.tv_usec) |
|
||||
(stime = ru->ru_stime.tv_sec * 1000000 + ru->ru_stime.tv_usec)) {
|
||||
ticks = ceill((long double)(utime + stime) / (1000000.L / CLK_TCK));
|
||||
fprintf(stderr, "%sneeded %,ldµs cpu (%d%% kernel)\n", PREFIX,
|
||||
utime + stime, (int)((long double)stime / (utime + stime) * 100));
|
||||
if (ru->ru_idrss) {
|
||||
fprintf(stderr, "%sneeded %,ldkb memory on average\n", PREFIX,
|
||||
lroundl(ru->ru_idrss / ticks));
|
||||
}
|
||||
if (ru->ru_isrss) {
|
||||
fprintf(stderr, "%sneeded %,ldkb stack on average\n", PREFIX,
|
||||
lroundl(ru->ru_isrss / ticks));
|
||||
}
|
||||
if (ru->ru_ixrss) {
|
||||
fprintf(stderr, "%smapped %,ldkb shared on average\n", PREFIX,
|
||||
lroundl(ru->ru_ixrss / ticks));
|
||||
}
|
||||
}
|
||||
if (ru->ru_minflt || ru->ru_majflt) {
|
||||
fprintf(stderr, "%scaused %,ld page faults (%d%% memcpy)\n", PREFIX,
|
||||
ru->ru_minflt + ru->ru_majflt,
|
||||
(int)((long double)ru->ru_minflt / (ru->ru_minflt + ru->ru_majflt) *
|
||||
100));
|
||||
}
|
||||
if (ru->ru_nvcsw + ru->ru_nivcsw > 1) {
|
||||
fprintf(stderr, "%s%,ld context switches (%d%% consensual)\n", PREFIX,
|
||||
ru->ru_nvcsw + ru->ru_nivcsw,
|
||||
(int)((long double)ru->ru_nvcsw / (ru->ru_nvcsw + ru->ru_nivcsw) *
|
||||
100));
|
||||
}
|
||||
if (ru->ru_msgrcv || ru->ru_msgsnd) {
|
||||
fprintf(stderr, "%sreceived %,ld message%s and sent %,ld\n", PREFIX,
|
||||
ru->ru_msgrcv, ru->ru_msgrcv == 1 ? "" : "s", ru->ru_msgsnd);
|
||||
}
|
||||
if (ru->ru_inblock || ru->ru_oublock) {
|
||||
fprintf(stderr, "%sperformed %,ld read%s and %,ld write i/o operations\n",
|
||||
PREFIX, ru->ru_inblock, ru->ru_inblock == 1 ? "" : "s",
|
||||
ru->ru_oublock);
|
||||
}
|
||||
if (ru->ru_nsignals) {
|
||||
fprintf(stderr, "%sreceived %,ld signals\n", PREFIX, ru->ru_nsignals);
|
||||
}
|
||||
if (ru->ru_nswap) {
|
||||
fprintf(stderr, "%sgot swapped %,ld times\n", PREFIX, ru->ru_nswap);
|
||||
}
|
||||
}
|
||||
|
||||
struct rusage rusage;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int pid, wstatus;
|
||||
long double ts1, ts2;
|
||||
sigset_t chldmask, savemask;
|
||||
struct sigaction dflt, ignore, saveint, savequit;
|
||||
|
||||
const char *prog = argv[0];
|
||||
if (!prog) prog = "rusage";
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "Usage: %s PROG [ARGS...]\n", argv[0]);
|
||||
return 1;
|
||||
tinyprint(2, prog, ": missing command\n", NULL);
|
||||
exit(1);
|
||||
}
|
||||
dflt.sa_flags = 0;
|
||||
dflt.sa_handler = SIG_DFL;
|
||||
sigemptyset(&dflt.sa_mask);
|
||||
|
||||
// block process management signals
|
||||
sigset_t mask, orig;
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGQUIT);
|
||||
sigaddset(&mask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &mask, &orig);
|
||||
|
||||
struct timespec started = timespec_real();
|
||||
|
||||
// launch subprocess
|
||||
int child = fork();
|
||||
if (child == -1) {
|
||||
perror(prog);
|
||||
exit(1);
|
||||
}
|
||||
if (!child) {
|
||||
sigprocmask(SIG_SETMASK, &orig, 0);
|
||||
execvp(argv[1], argv + 1);
|
||||
_Exit(127);
|
||||
}
|
||||
|
||||
// wait for subprocess
|
||||
int ws;
|
||||
struct rusage ru;
|
||||
struct sigaction ignore;
|
||||
ignore.sa_flags = 0;
|
||||
ignore.sa_handler = SIG_IGN;
|
||||
sigemptyset(&ignore.sa_mask);
|
||||
sigaction(SIGINT, &ignore, &saveint);
|
||||
sigaction(SIGQUIT, &ignore, &savequit);
|
||||
sigemptyset(&chldmask);
|
||||
sigaddset(&chldmask, SIGCHLD);
|
||||
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
|
||||
ts1 = nowl();
|
||||
CHECK_NE(-1, (pid = fork()));
|
||||
if (!pid) {
|
||||
sigaction(SIGINT, &dflt, 0);
|
||||
sigaction(SIGQUIT, &dflt, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
execvp(argv[1], argv + 1);
|
||||
fprintf(stderr, "exec failed %d\n", errno);
|
||||
_Exit(127);
|
||||
sigaction(SIGINT, &ignore, 0);
|
||||
sigaction(SIGQUIT, &ignore, 0);
|
||||
if (wait4(child, &ws, 0, &ru) == -1) {
|
||||
perror(prog);
|
||||
exit(1);
|
||||
}
|
||||
while (wait4(pid, &wstatus, 0, &rusage) == -1) {
|
||||
CHECK_EQ(EINTR, errno);
|
||||
}
|
||||
ts2 = nowl();
|
||||
sigaction(SIGINT, &saveint, 0);
|
||||
sigaction(SIGQUIT, &savequit, 0);
|
||||
sigprocmask(SIG_SETMASK, &savemask, 0);
|
||||
fprintf(stderr, "%stook %,ldµs wall time\n", PREFIX,
|
||||
(int64_t)((ts2 - ts1) * 1e6));
|
||||
PrintResourceReport(&rusage);
|
||||
if (WIFEXITED(wstatus)) {
|
||||
return WEXITSTATUS(wstatus);
|
||||
} else {
|
||||
return 128 + WTERMSIG(wstatus);
|
||||
|
||||
// compute wall time
|
||||
char strmicros[27];
|
||||
struct timespec ended = timespec_real();
|
||||
struct timespec elapsed = timespec_sub(ended, started);
|
||||
FormatInt64Thousands(strmicros, timespec_tomicros(elapsed));
|
||||
|
||||
// show report
|
||||
char *b = 0;
|
||||
appends(&b, "took ");
|
||||
appends(&b, strmicros);
|
||||
appends(&b, "µs wall time\n");
|
||||
AppendResourceReport(&b, &ru, "\n");
|
||||
write(2, b, appendz(b).i);
|
||||
|
||||
// propagate status
|
||||
if (WIFSIGNALED(ws)) {
|
||||
signal(WTERMSIG(ws), SIG_DFL);
|
||||
raise(WTERMSIG(ws));
|
||||
}
|
||||
return WEXITSTATUS(ws);
|
||||
}
|
||||
|
|
|
@ -129,6 +129,7 @@
|
|||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alg.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
@ -1787,7 +1788,7 @@ static int xvsnprintf(char *outbuf, unsigned length, const char *fmt,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int xvasprintf(char **sp, unsigned size, const char *f, va_list ap) {
|
||||
static int Xvasprintf(char **sp, unsigned size, const char *f, va_list ap) {
|
||||
char *s;
|
||||
int len;
|
||||
va_list ap2;
|
||||
|
@ -1858,7 +1859,7 @@ printfesque(2) static int Xasprintf(char **sp, const char *fmt, ...) {
|
|||
va_list ap;
|
||||
int ret;
|
||||
va_start(ap, fmt);
|
||||
ret = xvasprintf(sp, 0, fmt, ap);
|
||||
ret = Xvasprintf(sp, 0, fmt, ap);
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
@ -1871,7 +1872,7 @@ static void doformat(struct output *dest, const char *f, va_list ap) {
|
|||
setstackmark(&smark);
|
||||
s = dest->nextc;
|
||||
olen = dest->end - dest->nextc;
|
||||
len = xvasprintf(&s, olen, f, ap);
|
||||
len = Xvasprintf(&s, olen, f, ap);
|
||||
if (likely(olen > len)) {
|
||||
dest->nextc += len;
|
||||
goto out;
|
||||
|
@ -5821,7 +5822,9 @@ retry:
|
|||
linenoiseSetHintsCallback(ShellHint);
|
||||
linenoiseSetCompletionCallback(ShellCompletion);
|
||||
}
|
||||
if ((p = linenoiseWithHistory(">: ", "unbourne"))) {
|
||||
char ps1[256];
|
||||
snprintf(ps1, sizeof(ps1), "%d >: ", exitstatus);
|
||||
if ((p = linenoiseWithHistory(ps1, "unbourne"))) {
|
||||
nr = min(strlen(p), IBUFSIZ - 2);
|
||||
memcpy(buf, p, nr);
|
||||
buf[nr++] = '\n';
|
||||
|
|
3
third_party/python/freeze.c
vendored
3
third_party/python/freeze.c
vendored
|
@ -7,6 +7,7 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "third_party/python/Include/bytesobject.h"
|
||||
#include "third_party/python/Include/compile.h"
|
||||
#include "third_party/python/Include/fileutils.h"
|
||||
|
@ -18,6 +19,8 @@
|
|||
#include "third_party/python/Include/pythonrun.h"
|
||||
/* clang-format off */
|
||||
|
||||
STATIC_STACK_ALIGN(GetStackSize());
|
||||
|
||||
#define HEADER "\
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8 -*-│\n\
|
||||
│vi: set net ft=c ts=4 sts=4 sw=4 fenc=utf-8 :vi│\n\
|
||||
|
|
3
third_party/python/launch.c
vendored
3
third_party/python/launch.c
vendored
|
@ -13,6 +13,7 @@
|
|||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
#include "libc/x/x.h"
|
||||
#include "third_party/python/Include/abstract.h"
|
||||
|
@ -39,6 +40,8 @@
|
|||
#include "third_party/python/Include/yoink.h"
|
||||
/* clang-format off */
|
||||
|
||||
STATIC_STACK_ALIGN(GetStackSize());
|
||||
|
||||
#define USE_COSMO_CRASH MODE_DBG + 0
|
||||
|
||||
__static_yoink("zipos");
|
||||
|
|
3
third_party/python/pyobj.c
vendored
3
third_party/python/pyobj.c
vendored
|
@ -29,6 +29,7 @@
|
|||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "libc/stdio/append.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
|
@ -64,6 +65,8 @@
|
|||
#include "tool/build/lib/stripcomponents.h"
|
||||
/* clang-format off */
|
||||
|
||||
STATIC_STACK_ALIGN(GetStackSize());
|
||||
|
||||
__static_yoink("_PyUnicode_GetCode");
|
||||
|
||||
#define MANUAL "\
|
||||
|
|
3
third_party/python/pythontester.c
vendored
3
third_party/python/pythontester.c
vendored
|
@ -6,11 +6,14 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "third_party/python/Include/yoink.h"
|
||||
#include "third_party/python/runpythonmodule.h"
|
||||
#include "tool/args/args.h"
|
||||
// clang-format off
|
||||
|
||||
STATIC_STACK_ALIGN(GetStackSize());
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
|
3
third_party/python/repl.c
vendored
3
third_party/python/repl.c
vendored
|
@ -4,11 +4,14 @@
|
|||
│ Python 3 │
|
||||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/stack.h"
|
||||
#include "third_party/python/Include/yoink.h"
|
||||
#include "third_party/python/runpythonmodule.h"
|
||||
#include "tool/args/args.h"
|
||||
// clang-format off
|
||||
|
||||
STATIC_STACK_ALIGN(GetStackSize());
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue