]> git.ipfire.org Git - thirdparty/git.git/blame - trace2/tr2_tmr.h
documentation: add missing article
[thirdparty/git.git] / trace2 / tr2_tmr.h
CommitLineData
8ad57564
JH
1#ifndef TR2_TMR_H
2#define TR2_TMR_H
3
4#include "trace2.h"
5#include "trace2/tr2_tgt.h"
6
7/*
8 * Define a mechanism to allow "stopwatch" timers.
9 *
10 * Timers can be used to measure "interesting" activity that does not
11 * fit the "region" model, such as code called from many different
12 * regions (like zlib) and/or where data for individual calls are not
13 * interesting or are too numerous to be efficiently logged.
14 *
15 * Timer values are accumulated during program execution and emitted
16 * to the Trace2 logs at program exit.
17 *
18 * To make this model efficient, we define a compile-time fixed set of
19 * timers and timer ids using a "timer block" array in thread-local
20 * storage. This gives us constant time access to each timer within
21 * each thread, since we want start/stop operations to be as fast as
22 * possible. This lets us avoid the complexities of dynamically
23 * allocating a timer on the first use by a thread and/or possibly
24 * sharing that timer definition with other concurrent threads.
25 * However, this does require that we define time the set of timers at
26 * compile time.
27 *
28 * Each thread uses the timer block in its thread-local storage to
29 * compute partial sums for each timer (without locking). When a
30 * thread exits, those partial sums are (under lock) added to the
31 * global final sum.
32 *
33 * Using this "timer block" model costs ~48 bytes per timer per thread
34 * (we have about six uint64 fields per timer). This does increase
35 * the size of the thread-local storage block, but it is allocated (at
36 * thread create time) and not on the thread stack, so I'm not worried
37 * about the size.
38 *
39 * Partial sums for each timer are optionally emitted when a thread
40 * exits.
41 *
42 * Final sums for each timer are emitted between the "exit" and
43 * "atexit" events.
44 *
45 * A parallel "timer metadata" table contains the "category" and "name"
46 * fields for each timer. This eliminates the need to include those
47 * args in the various timer APIs.
48 */
49
50/*
51 * The definition of an individual timer and used by an individual
52 * thread.
53 */
54struct tr2_timer {
55 /*
56 * Total elapsed time for this timer in this thread in nanoseconds.
57 */
58 uint64_t total_ns;
59
60 /*
61 * The maximum and minimum interval values observed for this
62 * timer in this thread.
63 */
64 uint64_t min_ns;
65 uint64_t max_ns;
66
67 /*
68 * The value of the clock when this timer was started in this
69 * thread. (Undefined when the timer is not active in this
70 * thread.)
71 */
72 uint64_t start_ns;
73
74 /*
75 * Number of times that this timer has been started and stopped
76 * in this thread. (Recursive starts are ignored.)
77 */
78 uint64_t interval_count;
79
80 /*
81 * Number of nested starts on the stack in this thread. (We
82 * ignore recursive starts and use this to track the recursive
83 * calls.)
84 */
85 unsigned int recursion_count;
86};
87
88/*
89 * Metadata for a timer.
90 */
91struct tr2_timer_metadata {
92 const char *category;
93 const char *name;
94
95 /*
96 * True if we should emit per-thread events for this timer
97 * when individual threads exit.
98 */
99 unsigned int want_per_thread_events:1;
100};
101
102/*
103 * A compile-time fixed-size block of timers to insert into
104 * thread-local storage. This wrapper is used to avoid quirks
105 * of C and the usual need to pass an array size argument.
106 */
107struct tr2_timer_block {
108 struct tr2_timer timer[TRACE2_NUMBER_OF_TIMERS];
109};
110
111/*
112 * Private routines used by trace2.c to actually start/stop an
113 * individual timer in the current thread.
114 */
115void tr2_start_timer(enum trace2_timer_id tid);
116void tr2_stop_timer(enum trace2_timer_id tid);
117
118/*
119 * Add the current thread's timer data to the global totals.
120 * This is called during thread-exit.
121 *
122 * Caller must be holding the tr2tls_mutex.
123 */
124void tr2_update_final_timers(void);
125
126/*
127 * Emit per-thread timer data for the current thread.
128 * This is called during thread-exit.
129 */
130void tr2_emit_per_thread_timers(tr2_tgt_evt_timer_t *fn_apply);
131
132/*
133 * Emit global total timer values.
134 * This is called during atexit handling.
135 *
136 * Caller must be holding the tr2tls_mutex.
137 */
138void tr2_emit_final_timers(tr2_tgt_evt_timer_t *fn_apply);
139
140#endif /* TR2_TMR_H */