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


behaviortree_cpp_v4
Author(s): Davide Faconti
autogenerated on Fri Jun 28 2024 02:20:07