From b6555a0dc462f669e1b5a370c3efae0f5948a1ef Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 10 Apr 2019 13:58:29 -0700 Subject: [PATCH] Add print-rusage-self to fish This adds an option --print-rusage-self to the fish executable. When set, this option prints some getrusage stats to the console in a human-readable way. This will be used by upcoming benchmarking support. --- cmake/ConfigureChecks.cmake | 1 + config_cmake.h.in | 3 +++ sphinx_doc_src/cmds/fish.rst | 2 ++ src/fish.cpp | 43 ++++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+) diff --git a/cmake/ConfigureChecks.cmake b/cmake/ConfigureChecks.cmake index 2b8cd2a4a..b9e10d8b2 100644 --- a/cmake/ConfigureChecks.cmake +++ b/cmake/ConfigureChecks.cmake @@ -61,6 +61,7 @@ CHECK_CXX_SYMBOL_EXISTS(futimens sys/stat.h HAVE_FUTIMENS) CHECK_CXX_SYMBOL_EXISTS(futimes sys/time.h HAVE_FUTIMES) CHECK_CXX_SYMBOL_EXISTS(getifaddrs ifaddrs.h HAVE_GETIFADDRS) CHECK_CXX_SYMBOL_EXISTS(getpwent pwd.h HAVE_GETPWENT) +CHECK_CXX_SYMBOL_EXISTS(getrusage sys/resource.h HAVE_GETRUSAGE) CHECK_CXX_SYMBOL_EXISTS(gettext libintl.h HAVE_GETTEXT) CHECK_CXX_SYMBOL_EXISTS(killpg "sys/types.h;signal.h" HAVE_KILLPG) CHECK_CXX_SYMBOL_EXISTS(lrand48_r stdlib.h HAVE_LRAND48_R) diff --git a/config_cmake.h.in b/config_cmake.h.in index 8071546fd..2078896b2 100644 --- a/config_cmake.h.in +++ b/config_cmake.h.in @@ -31,6 +31,9 @@ /* Define to 1 if you have the `getpwent' function. */ #cmakedefine HAVE_GETPWENT 1 +/* Define to 1 if you have the 'getrusage' function. */ +#cmakedefine HAVE_GETRUSAGE 1 + /* Define to 1 if you have the `gettext' function. */ #cmakedefine HAVE_GETTEXT 1 diff --git a/sphinx_doc_src/cmds/fish.rst b/sphinx_doc_src/cmds/fish.rst index cb92df6ec..0a11cd531 100644 --- a/sphinx_doc_src/cmds/fish.rst +++ b/sphinx_doc_src/cmds/fish.rst @@ -30,6 +30,8 @@ The following options are available: - ``-p`` or ``--profile=PROFILE_FILE`` when fish exits, output timing information on all executed commands to the specified file +- ``--print-rusage-self`` when fish exits, output stats from getrusage + - ``-v`` or ``--version`` display version and exit - ``-D`` or ``--debug-stack-frames=DEBUG_LEVEL`` specify how many stack frames to display when debug messages are written. The default is zero. A value of 3 or 4 is usually sufficient to gain insight into how a given debug call was reached but you can specify a value up to 128. diff --git a/src/fish.cpp b/src/fish.cpp index 4b0f2c2c8..bf4b1006b 100644 --- a/src/fish.cpp +++ b/src/fish.cpp @@ -28,6 +28,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA #include #include #include +#include #include #include #include @@ -63,11 +64,45 @@ class fish_cmd_opts_t { std::vector batch_cmds; // Commands to execute after the shell's config has been read. std::vector postconfig_cmds; + /// Whether to print rusage-self stats after execution. + bool print_rusage_self{false}; }; /// If we are doing profiling, the filename to output to. static const char *s_profiling_output_filename = NULL; +/// \return a timeval converted to milliseconds. +long long tv_to_msec(const struct timeval &tv) { + long long msec = (long long)tv.tv_sec * 1000; // milliseconds per second + msec += tv.tv_usec / 1000; // microseconds per millisecond + return msec; +} + +static void print_rusage_self(FILE *fp) { +#ifndef HAVE_GETRUSAGE + fprintf(fp, "getrusage() not supported on this platform"); + return; +#else + struct rusage rs; + if (getrusage(RUSAGE_SELF, &rs)) { + perror("getrusage"); + return; + } +#if defined(__APPLE__) && defined(__MACH__) + // Macs use bytes. + long rss_kb = rs.ru_maxrss / 1024; +#else + // Everyone else uses KB. + long rss_kb = rs.ru_maxrss; +#endif + fprintf(fp, " rusage self:\n"); + fprintf(fp, " user time: %llu ms\n", tv_to_msec(rs.ru_utime)); + fprintf(fp, " sys time: %llu ms\n", tv_to_msec(rs.ru_stime)); + fprintf(fp, " max rss: %ld kb\n", rss_kb); + fprintf(fp, " signals: %ld\n", rs.ru_nsignals); +#endif +} + static bool has_suffix(const std::string &path, const char *suffix, bool ignore_case) { size_t pathlen = path.size(), suffixlen = std::strlen(suffix); return pathlen >= suffixlen && @@ -223,6 +258,7 @@ static int fish_parse_opt(int argc, char **argv, fish_cmd_opts_t *opts) { {"interactive", no_argument, NULL, 'i'}, {"login", no_argument, NULL, 'l'}, {"no-execute", no_argument, NULL, 'n'}, + {"print-rusage-self", no_argument, NULL, 1}, {"profile", required_argument, NULL, 'p'}, {"private", no_argument, NULL, 'P'}, {"help", no_argument, NULL, 'h'}, @@ -275,6 +311,10 @@ static int fish_parse_opt(int argc, char **argv, fish_cmd_opts_t *opts) { no_exec = 1; break; } + case 1: { + opts->print_rusage_self = true; + break; + } case 'p': { s_profiling_output_filename = optarg; g_profiling_active = true; @@ -450,6 +490,9 @@ int main(int argc, char **argv) { history_save_all(); proc_destroy(); + if (opts.print_rusage_self) { + print_rusage_self(stderr); + } exit_without_destructors(exit_status); return EXIT_FAILURE; // above line should always exit }