minitrace.h
Go to the documentation of this file.
00001 #ifndef MINITRACE_H
00002 #define MINITRACE_H
00003 
00004 // Minitrace
00005 //
00006 // Copyright 2014 by Henrik RydgÄrd
00007 // http://www.github.com/hrydgard/minitrace
00008 // Released under the MIT license.
00009 //
00010 // Ultra-light dependency free library for performance tracing C/C++ applications.
00011 // Produces traces compatible with Google Chrome's trace viewer.
00012 // Simply open "about:tracing" in Chrome and load the produced JSON.
00013 //
00014 // This contains far less template magic than the original libraries from Chrome
00015 // because this is meant to be usable from C.
00016 //
00017 // See README.md for a tutorial.
00018 //
00019 // The trace format is documented here:
00020 // https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/edit
00021 // More:
00022 // http://www.altdevblogaday.com/2012/08/21/using-chrometracing-to-view-your-inline-profiling-data/
00023 
00024 #include <inttypes.h>
00025 
00026 #define MTR_ENABLED
00027 
00028 // If MTR_ENABLED is not defined, Minitrace does nothing and has near zero overhead.
00029 // Preferably, set this flag in your build system. If you can't just uncomment this line.
00030 // #define MTR_ENABLED
00031 
00032 // By default, will collect up to 1000000 events, then you must flush.
00033 // It's recommended that you simply call mtr_flush on a background thread
00034 // occasionally. It's safe...ish.
00035 #define INTERNAL_MINITRACE_BUFFER_SIZE 1000000
00036 
00037 //#define MTR_ENABLED
00038 
00039 namespace minitrace {
00040 
00041 // Initializes Minitrace. Must be called very early during startup of your executable,
00042 // before any MTR_ statements..
00043 void mtr_init(const char *json_file);
00044 
00045 // Shuts down minitrace cleanly, flushing the trace buffer.
00046 void mtr_shutdown();
00047 
00048 // Lets you enable and disable Minitrace at runtime.
00049 // May cause strange discontinuities in the output.
00050 // Minitrace is enabled on startup by default.
00051 void mtr_start();
00052 void mtr_stop();
00053 
00054 // Flushes the collected data to disk, clearing the buffer for new data.
00055 void mtr_flush();
00056 
00057 // Returns the current time in seconds. Used internally by Minitrace. No caching.
00058 int64_t mtr_time_usec();
00059 
00060 // Registers a handler that will flush the trace on Ctrl+C.
00061 // Works on Linux and MacOSX, and in Win32 console applications.
00062 void mtr_register_sigint_handler();
00063 
00064 // Utility function that should rarely be used.
00065 // If str is semi dynamic, store it permanently in a small pool so we don't need to malloc it.
00066 // The pool fills up fast though and performance isn't great.
00067 // Returns a fixed string if the pool is full.
00068 const char *mtr_pool_string(const char *str);
00069 
00070 // Commented-out types will be supported in the future.
00071 typedef enum {
00072         MTR_ARG_TYPE_NONE = 0,
00073         MTR_ARG_TYPE_INT = 1,   // I
00074         // MTR_ARG_TYPE_FLOAT = 2,  // TODO
00075         // MTR_ARG_TYPE_DOUBLE = 3,  // TODO
00076         MTR_ARG_TYPE_STRING_CONST = 8,  // C
00077         MTR_ARG_TYPE_STRING_COPY = 9,
00078         // MTR_ARG_TYPE_JSON_COPY = 10,
00079 } mtr_arg_type;
00080 
00081 // TODO: Add support for more than one argument (metadata) per event
00082 // Having more costs speed and memory.
00083 #define MTR_MAX_ARGS 1
00084 
00085 // Only use the macros to call these.
00086 void internal_mtr_raw_event(const char *category, const char *name, char ph, void *id);
00087 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);
00088 
00089 #ifdef MTR_ENABLED
00090 
00091 // c - category. Can be filtered by in trace viewer (or at least that's the intention).
00092 //     A good use is to pass __FILE__, there are macros further below that will do it for you.
00093 // n - name. Pass __FUNCTION__ in most cases, unless you are marking up parts of one.
00094 
00095 // Scopes. In C++, use MTR_SCOPE. In C, always match them within the same scope.
00096 #define MTR_BEGIN(c, n) internal_mtr_raw_event(c, n, 'B', nullptr)
00097 #define MTR_END(c, n) internal_mtr_raw_event(c, n, 'E', nullptr)
00098 #define MTR_SCOPE(c, n) MTRScopedTrace ____mtr_scope(c, n)
00099 #define MTR_SCOPE_LIMIT(c, n, l) MTRScopedTraceLimit ____mtr_scope(c, n, l)
00100 
00101 // Async events. Can span threads. ID identifies which events to connect in the view.
00102 #define MTR_START(c, n, id) internal_mtr_raw_event(c, n, 'S', (void *)(id))
00103 #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))
00104 #define MTR_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'F', (void *)(id))
00105 
00106 // Flow events. Like async events, but displayed in a more fancy way in the viewer.
00107 #define MTR_FLOW_START(c, n, id) internal_mtr_raw_event(c, n, 's', (void *)(id))
00108 #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))
00109 #define MTR_FLOW_FINISH(c, n, id) internal_mtr_raw_event(c, n, 'f', (void *)(id))
00110 
00111 // The same macros, but with a single named argument which shows up as metadata in the viewer.
00112 // _I for int.
00113 // _C is for a const string arg.
00114 // _S will copy the string, freeing on flush (expensive but sometimes necessary).
00115 // but required if the string was generated dynamically.
00116 
00117 // Note that it's fine to match BEGIN_S with END and BEGIN with END_S, etc.
00118 #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))
00119 #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))
00120 #define MTR_SCOPE_C(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
00121 
00122 #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))
00123 #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))
00124 #define MTR_SCOPE_S(c, n, aname, astrval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_STRING_COPY, aname, (void *)(astrval))
00125 
00126 #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))
00127 #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))
00128 #define MTR_SCOPE_I(c, n, aname, aintval) MTRScopedTraceArg ____mtr_scope(c, n, MTR_ARG_TYPE_INT, aname, (void*)(intptr_t)(aintval))
00129 
00130 // Instant events. For things with no duration.
00131 #define MTR_INSTANT(c, n) internal_mtr_raw_event(c, n, 'I', nullptr)
00132 #define MTR_INSTANT_C(c, n, aname, astrval) internal_mtr_raw_event(c, n, 'I', 0, MTR_ARG_TYPE_STRING_CONST, aname, (void *)(astrval))
00133 #define MTR_INSTANT_I(c, n, aname, aintval) internal_mtr_raw_event(c, n, 'I', 0, MTR_ARG_TYPE_INT, aname, (void *)(aintval))
00134 
00135 // Counters (can't do multi-value counters yet)
00136 #define MTR_COUNTER(c, n, val) internal_mtr_raw_event_arg(c, n, 'C', 0, MTR_ARG_TYPE_INT, n, (void *)(intptr_t)(val))
00137 
00138 // Metadata. Call at the start preferably. Must be const strings.
00139 
00140 #define MTR_META_PROCESS_NAME(n) internal_mtr_raw_event_arg("", "process_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n))
00141 #define MTR_META_THREAD_NAME(n) internal_mtr_raw_event_arg("", "thread_name", 'M', 0, MTR_ARG_TYPE_STRING_COPY, "name", (void *)(n))
00142 #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))
00143 
00144 #else
00145 
00146 #define MTR_BEGIN(c, n)
00147 #define MTR_END(c, n)
00148 #define MTR_SCOPE(c, n)
00149 #define MTR_START(c, n, id)
00150 #define MTR_STEP(c, n, id, step)
00151 #define MTR_FINISH(c, n, id)
00152 #define MTR_FLOW_START(c, n, id)
00153 #define MTR_FLOW_STEP(c, n, id, step)
00154 #define MTR_FLOW_FINISH(c, n, id)
00155 #define MTR_INSTANT(c, n)
00156 
00157 #define MTR_BEGIN_C(c, n, aname, astrval)
00158 #define MTR_END_C(c, n, aname, astrval)
00159 #define MTR_SCOPE_C(c, n, aname, astrval)
00160 
00161 #define MTR_BEGIN_S(c, n, aname, astrval)
00162 #define MTR_END_S(c, n, aname, astrval)
00163 #define MTR_SCOPE_S(c, n, aname, astrval)
00164 
00165 #define MTR_BEGIN_I(c, n, aname, aintval)
00166 #define MTR_END_I(c, n, aname, aintval)
00167 #define MTR_SCOPE_I(c, n, aname, aintval)
00168 
00169 #define MTR_INSTANT(c, n)
00170 #define MTR_INSTANT_C(c, n, aname, astrval)
00171 #define MTR_INSTANT_I(c, n, aname, aintval)
00172 
00173 // Counters (can't do multi-value counters yet)
00174 #define MTR_COUNTER(c, n, val)
00175 
00176 // Metadata. Call at the start preferably. Must be const strings.
00177 
00178 #define MTR_META_PROCESS_NAME(n)
00179 
00180 #define MTR_META_THREAD_NAME(n)
00181 #define MTR_META_THREAD_SORT_INDEX(i)
00182 
00183 #endif
00184 
00185 // Shortcuts for simple function timing with automatic categories and names.
00186 
00187 #define MTR_BEGIN_FUNC() MTR_BEGIN(__FILE__, __FUNCTION__)
00188 #define MTR_END_FUNC() MTR_END(__FILE__, __FUNCTION__)
00189 #define MTR_SCOPE_FUNC() MTR_SCOPE(__FILE__, __FUNCTION__)
00190 #define MTR_INSTANT_FUNC() MTR_INSTANT(__FILE__, __FUNCTION__)
00191 #define MTR_SCOPE_FUNC_LIMIT_S(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, l)
00192 #define MTR_SCOPE_FUNC_LIMIT_MS(l) MTRScopedTraceLimit ____mtr_scope(__FILE__, __FUNCTION__, 1)
00193 
00194 // Same, but with a single argument of the usual types.
00195 #define MTR_BEGIN_FUNC_S(aname, arg) MTR_BEGIN_S(__FILE__, __FUNCTION__, aname, arg)
00196 #define MTR_END_FUNC_S(aname, arg) MTR_END_S(__FILE__, __FUNCTION__, aname, arg)
00197 #define MTR_SCOPE_FUNC_S(aname, arg) MTR_SCOPE_S(__FILE__, __FUNCTION__, aname, arg)
00198 
00199 #define MTR_BEGIN_FUNC_C(aname, arg) MTR_BEGIN_C(__FILE__, __FUNCTION__, aname, arg)
00200 #define MTR_END_FUNC_C(aname, arg) MTR_END_C(__FILE__, __FUNCTION__, aname, arg)
00201 #define MTR_SCOPE_FUNC_C(aname, arg) MTR_SCOPE_C(__FILE__, __FUNCTION__, aname, arg)
00202 
00203 #define MTR_BEGIN_FUNC_I(aname, arg) MTR_BEGIN_I(__FILE__, __FUNCTION__, aname, arg)
00204 #define MTR_END_FUNC_I(aname, arg) MTR_END_I(__FILE__, __FUNCTION__, aname, arg)
00205 #define MTR_SCOPE_FUNC_I(aname, arg) MTR_SCOPE_I(__FILE__, __FUNCTION__, aname, arg)
00206 
00207 
00208 #ifdef MTR_ENABLED
00209 // These are optimized to use X events (combined B and E). Much easier to do in C++ than in C.
00210 class MTRScopedTrace {
00211 public:
00212         MTRScopedTrace(const char *category, const char *name)
00213                 : category_(category), name_(name) {
00214     start_time_ = mtr_time_usec();
00215         }
00216         ~MTRScopedTrace() {
00217                 internal_mtr_raw_event(category_, name_, 'X', &start_time_);
00218         }
00219 
00220 private:
00221         const char *category_;
00222         const char *name_;
00223   int64_t start_time_;
00224 };
00225 
00226 // Only outputs a block if execution time exceeded the limit.
00227 // TODO: This will effectively call mtr_time_usec twice at the end, which is bad.
00228 class MTRScopedTraceLimit {
00229 public:
00230         MTRScopedTraceLimit(const char *category, const char *name, double limit_s)
00231                 : category_(category), name_(name), limit_(limit_s) {
00232     start_time_ = mtr_time_usec();
00233         }
00234         ~MTRScopedTraceLimit() {
00235     int64_t end_time = mtr_time_usec();
00236                 if (end_time - start_time_ >= limit_) {
00237                         internal_mtr_raw_event(category_, name_, 'X', &start_time_);
00238                 }
00239         }
00240 
00241 private:
00242         const char *category_;
00243         const char *name_;
00244         double start_time_;
00245         double limit_;
00246 };
00247 
00248 class MTRScopedTraceArg {
00249 public:
00250         MTRScopedTraceArg(const char *category, const char *name, mtr_arg_type arg_type, const char *arg_name, void *arg_value)
00251                 : category_(category), name_(name) {
00252                 internal_mtr_raw_event_arg(category, name, 'B', 0, arg_type, arg_name, arg_value);
00253         }
00254         ~MTRScopedTraceArg() {
00255                 internal_mtr_raw_event(category_, name_, 'E', 0);
00256         }
00257 
00258 private:
00259         const char *category_;
00260         const char *name_;
00261 };
00262 
00263 #endif
00264 
00265 } //end namespace
00266 
00267 #endif


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Feb 2 2019 03:50:10