Imported Upstream version 3.7
[platform/upstream/ccache.git] / src / minitrace.h
1 // Minitrace
2 //
3 // Copyright 2014 by Henrik RydgĂ„rd
4 // http://www.github.com/hrydgard/minitrace
5 // Released under the MIT license.
6 //
7 // Ultra-light dependency free library for performance tracing C/C++ applications.
8 // Produces traces compatible with Google Chrome's trace viewer.
9 // Simply open "about:tracing" in Chrome and load the produced JSON.
10 //
11 // This contains far less template magic than the original libraries from Chrome
12 // because this is meant to be usable from C.
13 //
14 // See README.md for a tutorial.
15 //
16 // The trace format is documented here:
17 // https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit
18 // More:
19 // http://www.altdevblogaday.com/2012/08/21/using-chrometracing-to-view-your-inline-profiling-data/
20
21 #ifndef MINITRACE_H
22 #define MINITRACE_H
23
24 #include <inttypes.h>
25
26 // If MTR_ENABLED is not defined, Minitrace does nothing and has near zero overhead.
27 // Preferably, set this flag in your build system. If you can't just uncomment this line.
28 // #define MTR_ENABLED
29
30 // By default, will collect up to 1000000 events, then you must flush.
31 // It's recommended that you simply call mtr_flush on a background thread
32 // occasionally. It's safe...ish.
33 #define INTERNAL_MINITRACE_BUFFER_SIZE 1000000
34
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38
39 // Initializes Minitrace. Must be called very early during startup of your executable,
40 // before any MTR_ statements.
41 void mtr_init(const char *json_file);
42 // Same as above, but allows passing in a custom stream (FILE *), as returned by
43 // fopen(). It should be opened for writing, preferably in binary mode to avoid
44 // processing of line endings (i.e. the "wb" mode).
45 void mtr_init_from_stream(void *stream);
46
47 // Shuts down minitrace cleanly, flushing the trace buffer.
48 void mtr_shutdown(void);
49
50 // Lets you enable and disable Minitrace at runtime.
51 // May cause strange discontinuities in the output.
52 // Minitrace is enabled on startup by default.
53 void mtr_start(void);
54 void mtr_stop(void);
55
56 // Flushes the collected data to disk, clearing the buffer for new data.
57 void mtr_flush(void);
58
59 // Returns the current time in seconds. Used internally by Minitrace. No caching.
60 double mtr_time_s(void);
61
62 // Registers a handler that will flush the trace on Ctrl+C.
63 // Works on Linux and MacOSX, and in Win32 console applications.
64 void mtr_register_sigint_handler(void);
65
66 // Utility function that should rarely be used.
67 // If str is semi dynamic, store it permanently in a small pool so we don't need to malloc it.
68 // The pool fills up fast though and performance isn't great.
69 // Returns a fixed string if the pool is full.
70 const char *mtr_pool_string(const char *str);
71
72 // Commented-out types will be supported in the future.
73 typedef enum {
74         MTR_ARG_TYPE_NONE = 0,
75         MTR_ARG_TYPE_INT = 1,   // I
76         // MTR_ARG_TYPE_FLOAT = 2,  // TODO
77         // MTR_ARG_TYPE_DOUBLE = 3,  // TODO
78         MTR_ARG_TYPE_STRING_CONST = 8,  // C
79         MTR_ARG_TYPE_STRING_COPY = 9,
80         // MTR_ARG_TYPE_JSON_COPY = 10,
81 } mtr_arg_type;
82
83 // TODO: Add support for more than one argument (metadata) per event
84 // Having more costs speed and memory.
85 #define MTR_MAX_ARGS 1
86
87 // Only use the macros to call these.
88 void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id);
89 void internal_mtr_raw_event_arg(const char *category, const char *name, char ph, void *id, mtr_arg_type arg_type, const char *arg_name, void *arg_value);
90
91 #ifdef MTR_ENABLED
92
93 // c - category. Can be filtered by in trace viewer (or at least that's the intention).
94 //     A good use is to pass __FILE__, there are macros further below that will do it for you.
95 // n - name. Pass __FUNCTION__ in most cases, unless you are marking up parts of one.
96
97 // Scopes. In C++, use MTR_SCOPE. In C, always match them within the same scope.
98 #define MTR_BEGIN(c, n) internal_mtr_raw_event(c, n, 'B', 0)
99 #define MTR_END(c, n) internal_mtr_raw_event(c, n, 'E', 0)
100 #define MTR_SCOPE(c, n) MTRScopedTrace ____mtr_scope(c, n)
101 #define MTR_SCOPE_LIMIT(c, n, l) MTRScopedTraceLimit ____mtr_scope(c, n, l)
102
103 // Async events. Can span threads. ID identifies which events to connect in the view.
104 #define MTR_START(c, n, id) internal_mtr_raw_event(c, n, 'S', (void *)(id))
105 #define MTR_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 'T', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step))
106 #define MTR_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'F', (void *)(id))
107
108 // Flow events. Like async events, but displayed in a more fancy way in the viewer.
109 #define MTR_FLOW_START(c, n, id) internal_mtr_raw_event(c, n, 's', (void *)(id))
110 #define MTR_FLOW_STEP(c, n, id, step) internal_mtr_raw_event_arg(c, n, 't', (void *)(id), MTR_ARG_TYPE_STRING_CONST, "step", (void *)(step))
111 #define MTR_FLOW_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'f', (void *)(id))
112
113 // The same macros, but with a single named argument which shows up as metadata in the viewer.
114 // _I for int.
115 // _C is for a const string arg.
116 // _S will copy the string, freeing on flush (expensive but sometimes necessary).
117 // but required if the string was generated dynamically.
118
119 // Note that it's fine to match BEGIN_S with END and BEGIN with END_S, etc.
120 #define MTR_BEGIN_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
121 #define MTR_END_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
122 #define MTR_SCOPE_C(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
123
124 #define MTR_BEGIN_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
125 #define MTR_END_S(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
126 #define MTR_SCOPE_S(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
127
128 #define MTR_BEGIN_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'B', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
129 #define MTR_END_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'E', 0, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
130 #define MTR_SCOPE_I(c, n, aname, aintval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
131
132 // Instant events. For things with no duration.
133 #define MTR_INSTANT(c, n) internal_mtr_raw_event(c, n, 'I', 0)
134 #define MTR_INSTANT_C(c, n, aname, astrval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
135 #define MTR_INSTANT_I(c, n, aname, aintval) internal_mtr_raw_event_arg(c, n, 'I', 0, MTR_ARG_TYPE_INT, aname, (void *)(aintval))
136
137 // Counters (can't do multi-value counters yet)
138 #define MTR_COUNTER(c, n, val) internal_mtr_raw_event_arg(c, n, 'C', 0, MTR_ARG_TYPE_INT, n, (void *)(intptr_t)(val))
139
140 // Metadata. Call at the start preferably. Must be const strings.
141
142 #define MTR_META_PROCESS_NAME(n) internal_mtr_raw_event_arg("", "process_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n))
143 #define MTR_META_THREAD_NAME(n) internal_mtr_raw_event_arg("", "thread_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n))
144 #define MTR_META_THREAD_SORT_INDEX(i) internal_mtr_raw_event_arg("", "thread_sort_index", 'M', 0, MTR_ARG_TYPE_INT, "sort_index", (void *)(i))
145
146 #else
147
148 #define MTR_BEGIN(c, n)
149 #define MTR_END(c, n)
150 #define MTR_SCOPE(c, n)
151 #define MTR_START(c, n, id)
152 #define MTR_STEP(c, n, id, step)
153 #define MTR_FINISH(c, n, id)
154 #define MTR_FLOW_START(c, n, id)
155 #define MTR_FLOW_STEP(c, n, id, step)
156 #define MTR_FLOW_FINISH(c, n, id)
157 #define MTR_INSTANT(c, n)
158
159 #define MTR_BEGIN_C(c, n, aname, astrval)
160 #define MTR_END_C(c, n, aname, astrval)
161 #define MTR_SCOPE_C(c, n, aname, astrval)
162
163 #define MTR_BEGIN_S(c, n, aname, astrval)
164 #define MTR_END_S(c, n, aname, astrval)
165 #define MTR_SCOPE_S(c, n, aname, astrval)
166
167 #define MTR_BEGIN_I(c, n, aname, aintval)
168 #define MTR_END_I(c, n, aname, aintval)
169 #define MTR_SCOPE_I(c, n, aname, aintval)
170
171 #define MTR_INSTANT(c, n)
172 #define MTR_INSTANT_C(c, n, aname, astrval)
173 #define MTR_INSTANT_I(c, n, aname, aintval)
174
175 // Counters (can't do multi-value counters yet)
176 #define MTR_COUNTER(c, n, val)
177
178 // Metadata. Call at the start preferably. Must be const strings.
179
180 #define MTR_META_PROCESS_NAME(n)
181
182 #define MTR_META_THREAD_NAME(n)
183 #define MTR_META_THREAD_SORT_INDEX(i)
184
185 #endif
186
187 // Shortcuts for simple function timing with automatic categories and names.
188
189 #define MTR_BEGIN_FUNC() MTR_BEGIN(__FILE__, __FUNCTION__)
190 #define MTR_END_FUNC() MTR_END(__FILE__, __FUNCTION__)
191 #define MTR_SCOPE_FUNC() MTR_SCOPE(__FILE__, __FUNCTION__)
192 #define MTR_INSTANT_FUNC() MTR_INSTANT(__FILE__, __FUNCTION__)
193 #define MTR_SCOPE_FUNC_LIMIT_S(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, l)
194 #define MTR_SCOPE_FUNC_LIMIT_MS(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, (double)l * 0.000001)
195
196 // Same, but with a single argument of the usual types.
197 #define MTR_BEGIN_FUNC_S(aname, arg) MTR_BEGIN_S(__FILE__, __FUNCTION__, aname, arg)
198 #define MTR_END_FUNC_S(aname, arg) MTR_END_S(__FILE__, __FUNCTION__, aname, arg)
199 #define MTR_SCOPE_FUNC_S(aname, arg) MTR_SCOPE_S(__FILE__, __FUNCTION__, aname, arg)
200
201 #define MTR_BEGIN_FUNC_C(aname, arg) MTR_BEGIN_C(__FILE__, __FUNCTION__, aname, arg)
202 #define MTR_END_FUNC_C(aname, arg) MTR_END_C(__FILE__, __FUNCTION__, aname, arg)
203 #define MTR_SCOPE_FUNC_C(aname, arg) MTR_SCOPE_C(__FILE__, __FUNCTION__, aname, arg)
204
205 #define MTR_BEGIN_FUNC_I(aname, arg) MTR_BEGIN_I(__FILE__, __FUNCTION__, aname, arg)
206 #define MTR_END_FUNC_I(aname, arg) MTR_END_I(__FILE__, __FUNCTION__, aname, arg)
207 #define MTR_SCOPE_FUNC_I(aname, arg) MTR_SCOPE_I(__FILE__, __FUNCTION__, aname, arg)
208
209 #ifdef __cplusplus
210 }
211
212 #ifdef MTR_ENABLED
213 // These are optimized to use X events (combined B and E). Much easier to do in C++ than in C.
214 class MTRScopedTrace {
215 public:
216         MTRScopedTrace(const char *category, const char *name)
217                 : category_(category), name_(name) {
218                 start_time_ = mtr_time_s();
219         }
220         ~MTRScopedTrace() {
221                 internal_mtr_raw_event(category_, name_, 'X', &start_time_);
222         }
223
224 private:
225         const char *category_;
226         const char *name_;
227         double start_time_;
228 };
229
230 // Only outputs a block if execution time exceeded the limit.
231 // TODO: This will effectively call mtr_time_s twice at the end, which is bad.
232 class MTRScopedTraceLimit {
233 public:
234         MTRScopedTraceLimit(const char *category, const char *name, double limit_s)
235                 : category_(category), name_(name), limit_(limit_s) {
236                 start_time_ = mtr_time_s();
237         }
238         ~MTRScopedTraceLimit() {
239                 double end_time = mtr_time_s();
240                 if (end_time - start_time_ >= limit_) {
241                         internal_mtr_raw_event(category_, name_, 'X', &start_time_);
242                 }
243         }
244
245 private:
246         const char *category_;
247         const char *name_;
248         double start_time_;
249         double limit_;
250 };
251
252 class MTRScopedTraceArg {
253 public:
254         MTRScopedTraceArg(const char *category, const char *name, mtr_arg_type arg_type, const char *arg_name, void *arg_value)
255                 : category_(category), name_(name) {
256                 internal_mtr_raw_event_arg(category, name, 'B', 0, arg_type, arg_name, arg_value);
257         }
258         ~MTRScopedTraceArg() {
259                 internal_mtr_raw_event(category_, name_, 'E', 0);
260         }
261
262 private:
263         const char *category_;
264         const char *name_;
265 };
266 #endif
267
268 #endif
269
270 #endif