diff options
author | Jeff Hostetler <jeffhost@microsoft.com> | 2022-10-24 16:41:06 +0300 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2022-10-24 22:45:26 +0300 |
commit | 8ad575646c0b1e927a05650a1ec64125121ae591 (patch) | |
tree | 17b2fb75a11ed67ca4490d59d10657c849efef38 /trace2.c | |
parent | 24a4c45da9e1255df43a87bec1f646b1efa69209 (diff) |
trace2: add stopwatch timers
Add stopwatch timer mechanism to Trace2.
Timers are an alternative to Trace2 Regions. Regions are useful for
measuring the time spent in various computation phases, such as the
time to read the index, time to scan for unstaged files, time to scan
for untracked files, and etc.
However, regions are not appropriate in all places. For example,
during a checkout, it would be very inefficient to use regions to
measure the total time spent inflating objects from the ODB from
across the entire lifetime of the process; a per-unzip() region would
flood the output and significantly slow the command; and some form of
post-processing would be requried to compute the time spent in unzip().
Timers can be used to measure a series of timer intervals and emit
a single summary event (at thread and/or process exit).
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'trace2.c')
-rw-r--r-- | trace2.c | 75 |
1 files changed, 75 insertions, 0 deletions
@@ -13,6 +13,7 @@ #include "trace2/tr2_sysenv.h" #include "trace2/tr2_tgt.h" #include "trace2/tr2_tls.h" +#include "trace2/tr2_tmr.h" static int trace2_enabled; @@ -83,6 +84,23 @@ static void tr2_tgt_disable_builtins(void) tgt_j->pfn_term(); } +/* + * The signature of this function must match the pfn_timer + * method in the targets. (Think of this is an apply operation + * across the set of active targets.) + */ +static void tr2_tgt_emit_a_timer(const struct tr2_timer_metadata *meta, + const struct tr2_timer *timer, + int is_final_data) +{ + struct tr2_tgt *tgt_j; + int j; + + for_each_wanted_builtin (j, tgt_j) + if (tgt_j->pfn_timer) + tgt_j->pfn_timer(meta, timer, is_final_data); +} + static int tr2main_exit_code; /* @@ -110,6 +128,26 @@ static void tr2main_atexit_handler(void) */ tr2tls_pop_unwind_self(); + /* + * Some timers want per-thread details. If the main thread + * used one of those timers, emit the details now (before + * we emit the aggregate timer values). + */ + tr2_emit_per_thread_timers(tr2_tgt_emit_a_timer); + + /* + * Add stopwatch timer data for the main thread to the final + * totals. And then emit the final timer values. + * + * Technically, we shouldn't need to hold the lock to update + * and output the final_timer_block (since all other threads + * should be dead by now), but it doesn't hurt anything. + */ + tr2tls_lock(); + tr2_update_final_timers(); + tr2_emit_final_timers(tr2_tgt_emit_a_timer); + tr2tls_unlock(); + for_each_wanted_builtin (j, tgt_j) if (tgt_j->pfn_atexit) tgt_j->pfn_atexit(us_elapsed_absolute, @@ -541,6 +579,21 @@ void trace2_thread_exit_fl(const char *file, int line) tr2tls_pop_unwind_self(); us_elapsed_thread = tr2tls_region_elasped_self(us_now); + /* + * Some timers want per-thread details. If this thread used + * one of those timers, emit the details now. + */ + tr2_emit_per_thread_timers(tr2_tgt_emit_a_timer); + + /* + * Add stopwatch timer data from the current (non-main) thread + * to the final totals. (We'll accumulate data for the main + * thread later during "atexit".) + */ + tr2tls_lock(); + tr2_update_final_timers(); + tr2tls_unlock(); + for_each_wanted_builtin (j, tgt_j) if (tgt_j->pfn_thread_exit_fl) tgt_j->pfn_thread_exit_fl(file, line, @@ -795,6 +848,28 @@ void trace2_printf_fl(const char *file, int line, const char *fmt, ...) va_end(ap); } +void trace2_timer_start(enum trace2_timer_id tid) +{ + if (!trace2_enabled) + return; + + if (tid < 0 || tid >= TRACE2_NUMBER_OF_TIMERS) + BUG("trace2_timer_start: invalid timer id: %d", tid); + + tr2_start_timer(tid); +} + +void trace2_timer_stop(enum trace2_timer_id tid) +{ + if (!trace2_enabled) + return; + + if (tid < 0 || tid >= TRACE2_NUMBER_OF_TIMERS) + BUG("trace2_timer_stop: invalid timer id: %d", tid); + + tr2_stop_timer(tid); +} + const char *trace2_session_id(void) { return tr2_sid_get(); |