diff --git a/pressure-vessel/utils.c b/pressure-vessel/utils.c index 47ccda7c371db205fdc32d6046a49f4699d4b1a0..49843c57af6985848a6fa64df90b4ecf72571ec5 100644 --- a/pressure-vessel/utils.c +++ b/pressure-vessel/utils.c @@ -36,6 +36,7 @@ #include "libglnx/libglnx.h" #include "steam-runtime-tools/glib-backports-internal.h" +#include "steam-runtime-tools/profiling-internal.h" #include "steam-runtime-tools/resolve-in-sysroot-internal.h" #include "steam-runtime-tools/utils-internal.h" #include "flatpak-bwrap-private.h" @@ -1028,7 +1029,10 @@ pv_set_up_logging (gboolean opt_verbose) log_levels |= G_LOG_LEVEL_INFO; if (opt_verbose) - log_levels |= G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO; + { + log_levels |= G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO; + _srt_profiling_enable (); + } g_log_set_handler (G_LOG_DOMAIN, log_levels, opt_timestamp ? pv_log_to_stderr_with_timestamp : pv_log_to_stderr, diff --git a/steam-runtime-tools/meson.build b/steam-runtime-tools/meson.build index 6e6a8ef496f1253c3e4213a6f508a56a82c583de..7f345e2915407017dedac78a76ab8b82519cd0f0 100644 --- a/steam-runtime-tools/meson.build +++ b/steam-runtime-tools/meson.build @@ -46,6 +46,8 @@ libsteamrt_sources = [ 'locale.c', 'os-internal.h', 'os.c', + 'profiling-internal.h', + 'profiling.c', 'resolve-in-sysroot-internal.h', 'resolve-in-sysroot.c', 'runtime-internal.h', diff --git a/steam-runtime-tools/profiling-internal.h b/steam-runtime-tools/profiling-internal.h new file mode 100644 index 0000000000000000000000000000000000000000..72906dcaa430a8fb17bf0b9a015cd128f7026a45 --- /dev/null +++ b/steam-runtime-tools/profiling-internal.h @@ -0,0 +1,40 @@ +/*<private_header>*/ +/* + * Copyright © 2021 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#pragma once + +#include <glib.h> +#include <libglnx.h> + +#include <steam-runtime-tools/macros.h> + +typedef struct _SrtProfilingTimer SrtProfilingTimer; + +G_GNUC_PRINTF (1, 2) G_GNUC_INTERNAL +SrtProfilingTimer *_srt_profiling_start (const char *format, ...); +G_GNUC_INTERNAL void _srt_profiling_end (SrtProfilingTimer *start); +G_GNUC_INTERNAL void _srt_profiling_enable (void); +G_DEFINE_AUTOPTR_CLEANUP_FUNC (SrtProfilingTimer, _srt_profiling_end) diff --git a/steam-runtime-tools/profiling.c b/steam-runtime-tools/profiling.c new file mode 100644 index 0000000000000000000000000000000000000000..8abe4be7828334bf32c4c7c50ed1a1031ad93f66 --- /dev/null +++ b/steam-runtime-tools/profiling.c @@ -0,0 +1,116 @@ +/* + * Copyright © 2021 Collabora Ltd. + * + * SPDX-License-Identifier: MIT + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "steam-runtime-tools/profiling-internal.h" + +#include <errno.h> +#include <sys/times.h> + +/* If strictly positive, profiling is enabled. */ +static long profiling_ticks_per_sec = 0; + +/* + * Enable time measurement and profiling messages. + */ +void +_srt_profiling_enable (void) +{ + errno = 0; + profiling_ticks_per_sec = sysconf (_SC_CLK_TCK); + + if (profiling_ticks_per_sec <= 0) + g_warning ("Unable to enable profiling: %s", g_strerror (errno)); + else + g_message ("Enabled profiling"); +} + +struct _SrtProfilingTimer +{ + char *message; + clock_t wallclock; + struct tms cpu; +}; + +/* + * Start a time measurement. Must be paired with _srt_profiling_end(), + * unless %NULL is returned. + * + * Returns: (transfer full): an object representing the start time, + * or %NULL if profiling is disabled + */ +SrtProfilingTimer * +_srt_profiling_start (const char *format, + ...) +{ + SrtProfilingTimer *ret; + va_list args; + + if (profiling_ticks_per_sec <= 0) + return NULL; + + ret = g_new0 (SrtProfilingTimer, 1); + va_start (args, format); + ret->message = g_strdup_vprintf (format, args); + va_end (args); + + g_message ("Profiling: start: %s", ret->message); + ret->wallclock = times (&ret->cpu); + return ret; +} + +/* + * @start: (nullable) (transfer full): The start of the measurement + * + * Finish a time measurement and log how much real (wallclock) time, + * user CPU time and system CPU type was taken. + * + * A `g_autoptr(SrtProfilingTimer)` automatically ends profiling when the + * timer goes out of scope. + */ +void +_srt_profiling_end (SrtProfilingTimer *start) +{ + clock_t end; + struct tms end_cpu; + + if (start == NULL) + return; + + end = times (&end_cpu); + + g_message ("Profiling: end (real %.1fs, user %.1fs, sys %.1fs): %s", + (end - start->wallclock) / (double) profiling_ticks_per_sec, + (end_cpu.tms_utime + + end_cpu.tms_cutime + - start->cpu.tms_utime + - start->cpu.tms_cutime) / (double) profiling_ticks_per_sec, + (end_cpu.tms_stime + + end_cpu.tms_cstime + - start->cpu.tms_stime + - start->cpu.tms_cstime) / (double) profiling_ticks_per_sec, + start->message); + g_free (start->message); + g_free (start); +}