trace_event.h (43798B)
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Trace events are for tracking application performance and resource usage. 6 // Macros are provided to track: 7 // Begin and end of function calls 8 // Counters 9 // 10 // Events are issued against categories. Whereas LOG's 11 // categories are statically defined, TRACE categories are created 12 // implicitly with a string. For example: 13 // TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent") 14 // 15 // Events can be INSTANT, or can be pairs of BEGIN and END in the same scope: 16 // TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly") 17 // doSomethingCostly() 18 // TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly") 19 // Note: our tools can't always determine the correct BEGIN/END pairs unless 20 // these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them 21 // to be in separate scopes. 22 // 23 // A common use case is to trace entire function scopes. This 24 // issues a trace BEGIN and END automatically: 25 // void doSomethingCostly() { 26 // TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly"); 27 // ... 28 // } 29 // 30 // Additional parameters can be associated with an event: 31 // void doSomethingCostly2(int howMuch) { 32 // TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly", 33 // "howMuch", howMuch); 34 // ... 35 // } 36 // 37 // The trace system will automatically add to this information the 38 // current process id, thread id, and a timestamp in microseconds. 39 // 40 // To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and 41 // ASYNC_END: 42 // [single threaded sender code] 43 // static int send_count = 0; 44 // ++send_count; 45 // TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count); 46 // Send(new MyMessage(send_count)); 47 // [receive code] 48 // void OnMyMessage(send_count) { 49 // TRACE_EVENT_ASYNC_END0("ipc", "message", send_count); 50 // } 51 // The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs. 52 // ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can 53 // be used for the ID parameter, and they will be mangled internally so that 54 // the same pointer on two different processes will not match. For example: 55 // class MyTracedClass { 56 // public: 57 // MyTracedClass() { 58 // TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this); 59 // } 60 // ~MyTracedClass() { 61 // TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this); 62 // } 63 // } 64 // 65 // Trace event also supports counters, which is a way to track a quantity 66 // as it varies over time. Counters are created with the following macro: 67 // TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue); 68 // 69 // Counters are process-specific. The macro itself can be issued from any 70 // thread, however. 71 // 72 // Sometimes, you want to track two counters at once. You can do this with two 73 // counter macros: 74 // TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]); 75 // TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]); 76 // Or you can do it with a combined macro: 77 // TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter", 78 // "bytesPinned", g_myCounterValue[0], 79 // "bytesAllocated", g_myCounterValue[1]); 80 // This indicates to the tracing UI that these counters should be displayed 81 // in a single graph, as a summed area chart. 82 // 83 // Since counters are in a global namespace, you may want to disembiguate with a 84 // unique ID, by using the TRACE_COUNTER_ID* variations. 85 // 86 // By default, trace collection is compiled in, but turned off at runtime. 87 // Collecting trace data is the responsibility of the embedding 88 // application. In Chrome's case, navigating to about:tracing will turn on 89 // tracing and display data collected across all active processes. 90 // 91 // 92 // Memory scoping note: 93 // Tracing copies the pointers, not the string content, of the strings passed 94 // in for category, name, and arg_names. Thus, the following code will 95 // cause problems: 96 // char* str = strdup("impprtantName"); 97 // TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD! 98 // free(str); // Trace system now has dangling pointer 99 // 100 // To avoid this issue with the |name| and |arg_name| parameters, use the 101 // TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead. 102 // Notes: The category must always be in a long-lived char* (i.e. static const). 103 // The |arg_values|, when used, are always deep copied with the _COPY 104 // macros. 105 // 106 // When are string argument values copied: 107 // const char* arg_values are only referenced by default: 108 // TRACE_EVENT1("category", "name", 109 // "arg1", "literal string is only referenced"); 110 // Use TRACE_STR_COPY to force copying of a const char*: 111 // TRACE_EVENT1("category", "name", 112 // "arg1", TRACE_STR_COPY("string will be copied")); 113 // std::string arg_values are always copied: 114 // TRACE_EVENT1("category", "name", 115 // "arg1", std::string("string will be copied")); 116 // 117 // 118 // Thread Safety: 119 // A thread safe singleton and mutex are used for thread safety. Category 120 // enabled flags are used to limit the performance impact when the system 121 // is not enabled. 122 // 123 // TRACE_EVENT macros first cache a pointer to a category. The categories are 124 // statically allocated and safe at all times, even after exit. Fetching a 125 // category is protected by the TraceLog::lock_. Multiple threads initializing 126 // the static variable is safe, as they will be serialized by the lock and 127 // multiple calls will return the same pointer to the category. 128 // 129 // Then the category_enabled flag is checked. This is a unsigned char, and 130 // not intended to be multithread safe. It optimizes access to addTraceEvent 131 // which is threadsafe internally via TraceLog::lock_. The enabled flag may 132 // cause some threads to incorrectly call or skip calling addTraceEvent near 133 // the time of the system being enabled or disabled. This is acceptable as 134 // we tolerate some data loss while the system is being enabled/disabled and 135 // because addTraceEvent is threadsafe internally and checks the enabled state 136 // again under lock. 137 // 138 // Without the use of these static category pointers and enabled flags all 139 // trace points would carry a significant performance cost of aquiring a lock 140 // and resolving the category. 141 142 #ifndef COMMON_TRACE_EVENT_H_ 143 #define COMMON_TRACE_EVENT_H_ 144 145 #include <string> 146 147 #include "common/event_tracer.h" 148 149 // By default, const char* argument values are assumed to have long-lived scope 150 // and will not be copied. Use this macro to force a const char* to be copied. 151 #define TRACE_STR_COPY(str) WebCore::TraceEvent::TraceStringWithCopy(str) 152 153 // Records a pair of begin and end events called "name" for the current 154 // scope, with 0, 1 or 2 associated arguments. If the category is not 155 // enabled, then this does nothing. 156 // - category and name strings must have application lifetime (statics or 157 // literals). They may not include " chars. 158 #define TRACE_EVENT0(platform, category, name) \ 159 INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name) 160 #define TRACE_EVENT1(platform, category, name, arg1_name, arg1_val) \ 161 INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, arg1_name, arg1_val) 162 #define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ 163 INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, arg1_name, arg1_val, arg2_name, \ 164 arg2_val) 165 166 // Records a single event called "name" immediately, with 0, 1 or 2 167 // associated arguments. If the category is not enabled, then this 168 // does nothing. 169 // - category and name strings must have application lifetime (statics or 170 // literals). They may not include " chars. 171 #define TRACE_EVENT_INSTANT0(platform, category, name) \ 172 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \ 173 TRACE_EVENT_FLAG_NONE) 174 #define TRACE_EVENT_INSTANT1(platform, category, name, arg1_name, arg1_val) \ 175 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \ 176 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) 177 #define TRACE_EVENT_INSTANT2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ 178 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \ 179 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) 180 #define TRACE_EVENT_COPY_INSTANT0(platform, category, name) \ 181 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \ 182 TRACE_EVENT_FLAG_COPY) 183 #define TRACE_EVENT_COPY_INSTANT1(platform, category, name, arg1_name, arg1_val) \ 184 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \ 185 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) 186 #define TRACE_EVENT_COPY_INSTANT2(platform, category, name, arg1_name, arg1_val, arg2_name, \ 187 arg2_val) \ 188 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_INSTANT, category, name, \ 189 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val) 190 191 // Records a single BEGIN event called "name" immediately, with 0, 1 or 2 192 // associated arguments. If the category is not enabled, then this 193 // does nothing. 194 // - category and name strings must have application lifetime (statics or 195 // literals). They may not include " chars. 196 #define TRACE_EVENT_BEGIN0(platform, category, name) \ 197 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \ 198 TRACE_EVENT_FLAG_NONE) 199 #define TRACE_EVENT_BEGIN1(platform, category, name, arg1_name, arg1_val) \ 200 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \ 201 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) 202 #define TRACE_EVENT_BEGIN2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ 203 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \ 204 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) 205 #define TRACE_EVENT_COPY_BEGIN0(platform, category, name) \ 206 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \ 207 TRACE_EVENT_FLAG_COPY) 208 #define TRACE_EVENT_COPY_BEGIN1(platform, category, name, arg1_name, arg1_val) \ 209 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \ 210 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) 211 #define TRACE_EVENT_COPY_BEGIN2(platform, category, name, arg1_name, arg1_val, arg2_name, \ 212 arg2_val) \ 213 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_BEGIN, category, name, \ 214 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val) 215 216 // Records a single END event for "name" immediately. If the category 217 // is not enabled, then this does nothing. 218 // - category and name strings must have application lifetime (statics or 219 // literals). They may not include " chars. 220 #define TRACE_EVENT_END0(platform, category, name) \ 221 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, TRACE_EVENT_FLAG_NONE) 222 #define TRACE_EVENT_END1(platform, category, name, arg1_name, arg1_val) \ 223 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \ 224 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) 225 #define TRACE_EVENT_END2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ 226 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \ 227 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, arg2_val) 228 #define TRACE_EVENT_COPY_END0(platform, category, name) \ 229 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, TRACE_EVENT_FLAG_COPY) 230 #define TRACE_EVENT_COPY_END1(platform, category, name, arg1_name, arg1_val) \ 231 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \ 232 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) 233 #define TRACE_EVENT_COPY_END2(platform, category, name, arg1_name, arg1_val, arg2_name, arg2_val) \ 234 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_END, category, name, \ 235 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, arg2_val) 236 237 // Records the value of a counter called "name" immediately. Value 238 // must be representable as a 32 bit integer. 239 // - category and name strings must have application lifetime (statics or 240 // literals). They may not include " chars. 241 #define TRACE_COUNTER1(platform, category, name, value) \ 242 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \ 243 TRACE_EVENT_FLAG_NONE, "value", static_cast<int>(value)) 244 #define TRACE_COPY_COUNTER1(platform, category, name, value) \ 245 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \ 246 TRACE_EVENT_FLAG_COPY, "value", static_cast<int>(value)) 247 248 // Records the values of a multi-parted counter called "name" immediately. 249 // The UI will treat value1 and value2 as parts of a whole, displaying their 250 // values as a stacked-bar chart. 251 // - category and name strings must have application lifetime (statics or 252 // literals). They may not include " chars. 253 #define TRACE_COUNTER2(platform, category, name, value1_name, value1_val, value2_name, value2_val) \ 254 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \ 255 TRACE_EVENT_FLAG_NONE, value1_name, static_cast<int>(value1_val), \ 256 value2_name, static_cast<int>(value2_val)) 257 #define TRACE_COPY_COUNTER2(platform, category, name, value1_name, value1_val, value2_name, \ 258 value2_val) \ 259 INTERNAL_TRACE_EVENT_ADD(platform, TRACE_EVENT_PHASE_COUNTER, category, name, \ 260 TRACE_EVENT_FLAG_COPY, value1_name, static_cast<int>(value1_val), \ 261 value2_name, static_cast<int>(value2_val)) 262 263 // Records the value of a counter called "name" immediately. Value 264 // must be representable as a 32 bit integer. 265 // - category and name strings must have application lifetime (statics or 266 // literals). They may not include " chars. 267 // - |id| is used to disambiguate counters with the same name. It must either 268 // be a pointer or an integer value up to 64 bits. If it's a pointer, the bits 269 // will be xored with a hash of the process ID so that the same pointer on 270 // two different processes will not collide. 271 #define TRACE_COUNTER_ID1(platform, category, name, id, value) \ 272 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, \ 273 TRACE_EVENT_FLAG_NONE, "value", static_cast<int>(value)) 274 #define TRACE_COPY_COUNTER_ID1(platform, category, name, id, value) \ 275 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, \ 276 TRACE_EVENT_FLAG_COPY, "value", static_cast<int>(value)) 277 278 // Records the values of a multi-parted counter called "name" immediately. 279 // The UI will treat value1 and value2 as parts of a whole, displaying their 280 // values as a stacked-bar chart. 281 // - category and name strings must have application lifetime (statics or 282 // literals). They may not include " chars. 283 // - |id| is used to disambiguate counters with the same name. It must either 284 // be a pointer or an integer value up to 64 bits. If it's a pointer, the bits 285 // will be xored with a hash of the process ID so that the same pointer on 286 // two different processes will not collide. 287 #define TRACE_COUNTER_ID2(platform, category, name, id, value1_name, value1_val, value2_name, \ 288 value2_val) \ 289 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ 290 platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, TRACE_EVENT_FLAG_NONE, \ 291 value1_name, static_cast<int>(value1_val), value2_name, static_cast<int>(value2_val)) 292 #define TRACE_COPY_COUNTER_ID2(platform, category, name, id, value1_name, value1_val, value2_name, \ 293 value2_val) \ 294 INTERNAL_TRACE_EVENT_ADD_WITH_ID( \ 295 platform, TRACE_EVENT_PHASE_COUNTER, category, name, id, TRACE_EVENT_FLAG_COPY, \ 296 value1_name, static_cast<int>(value1_val), value2_name, static_cast<int>(value2_val)) 297 298 // Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2 299 // associated arguments. If the category is not enabled, then this 300 // does nothing. 301 // - category and name strings must have application lifetime (statics or 302 // literals). They may not include " chars. 303 // - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC 304 // events are considered to match if their category, name and id values all 305 // match. |id| must either be a pointer or an integer value up to 64 bits. If 306 // it's a pointer, the bits will be xored with a hash of the process ID so 307 // that the same pointer on two different processes will not collide. 308 // An asynchronous operation can consist of multiple phases. The first phase is 309 // defined by the ASYNC_BEGIN calls. Additional phases can be defined using the 310 // ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END. 311 // An async operation can span threads and processes, but all events in that 312 // operation must use the same |name| and |id|. Each event can have its own 313 // args. 314 #define TRACE_EVENT_ASYNC_BEGIN0(platform, category, name, id) \ 315 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \ 316 TRACE_EVENT_FLAG_NONE) 317 #define TRACE_EVENT_ASYNC_BEGIN1(platform, category, name, id, arg1_name, arg1_val) \ 318 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \ 319 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) 320 #define TRACE_EVENT_ASYNC_BEGIN2(platform, category, name, id, arg1_name, arg1_val, arg2_name, \ 321 arg2_val) \ 322 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \ 323 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, \ 324 arg2_val) 325 #define TRACE_EVENT_COPY_ASYNC_BEGIN0(platform, category, name, id) \ 326 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \ 327 TRACE_EVENT_FLAG_COPY) 328 #define TRACE_EVENT_COPY_ASYNC_BEGIN1(platform, category, name, id, arg1_name, arg1_val) \ 329 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \ 330 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) 331 #define TRACE_EVENT_COPY_ASYNC_BEGIN2(platform, category, name, id, arg1_name, arg1_val, \ 332 arg2_name, arg2_val) \ 333 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_BEGIN, category, name, id, \ 334 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, \ 335 arg2_val) 336 337 // Records a single ASYNC_STEP event for |step| immediately. If the category 338 // is not enabled, then this does nothing. The |name| and |id| must match the 339 // ASYNC_BEGIN event above. The |step| param identifies this step within the 340 // async event. This should be called at the beginning of the next phase of an 341 // asynchronous operation. 342 #define TRACE_EVENT_ASYNC_STEP0(platform, category, name, id, step) \ 343 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \ 344 TRACE_EVENT_FLAG_NONE, "step", step) 345 #define TRACE_EVENT_ASYNC_STEP1(platform, category, name, id, step, arg1_name, arg1_val) \ 346 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \ 347 TRACE_EVENT_FLAG_NONE, "step", step, arg1_name, arg1_val) 348 #define TRACE_EVENT_COPY_ASYNC_STEP0(platform, category, name, id, step) \ 349 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \ 350 TRACE_EVENT_FLAG_COPY, "step", step) 351 #define TRACE_EVENT_COPY_ASYNC_STEP1(platform, category, name, id, step, arg1_name, arg1_val) \ 352 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_STEP, category, name, id, \ 353 TRACE_EVENT_FLAG_COPY, "step", step, arg1_name, arg1_val) 354 355 // Records a single ASYNC_END event for "name" immediately. If the category 356 // is not enabled, then this does nothing. 357 #define TRACE_EVENT_ASYNC_END0(platform, category, name, id) \ 358 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \ 359 TRACE_EVENT_FLAG_NONE) 360 #define TRACE_EVENT_ASYNC_END1(platform, category, name, id, arg1_name, arg1_val) \ 361 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \ 362 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val) 363 #define TRACE_EVENT_ASYNC_END2(platform, category, name, id, arg1_name, arg1_val, arg2_name, \ 364 arg2_val) \ 365 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \ 366 TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, arg2_name, \ 367 arg2_val) 368 #define TRACE_EVENT_COPY_ASYNC_END0(platform, category, name, id) \ 369 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \ 370 TRACE_EVENT_FLAG_COPY) 371 #define TRACE_EVENT_COPY_ASYNC_END1(platform, category, name, id, arg1_name, arg1_val) \ 372 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \ 373 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val) 374 #define TRACE_EVENT_COPY_ASYNC_END2(platform, category, name, id, arg1_name, arg1_val, arg2_name, \ 375 arg2_val) \ 376 INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, TRACE_EVENT_PHASE_ASYNC_END, category, name, id, \ 377 TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, arg2_name, \ 378 arg2_val) 379 380 // Creates a scope of a sampling state with the given category and name (both must 381 // be constant strings). These states are intended for a sampling profiler. 382 // Implementation note: we store category and name together because we don't 383 // want the inconsistency/expense of storing two pointers. 384 // |thread_bucket| is [0..2] and is used to statically isolate samples in one 385 // thread from others. 386 // 387 // { // The sampling state is set within this scope. 388 // TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name"); 389 // ...; 390 // } 391 #define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ 392 TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(category "\0" name); 393 394 // Returns a current sampling state of the given bucket. 395 // The format of the returned string is "category\0name". 396 #define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \ 397 TraceEvent::SamplingStateScope<bucket_number>::current() 398 399 // Sets a current sampling state of the given bucket. 400 // |category| and |name| have to be constant strings. 401 #define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \ 402 TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name) 403 404 // Sets a current sampling state of the given bucket. 405 // |categoryAndName| doesn't need to be a constant string. 406 // The format of the string is "category\0name". 407 #define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \ 408 TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName) 409 410 // Syntactic sugars for the sampling tracing in the main thread. 411 #define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \ 412 TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name) 413 #define TRACE_EVENT_GET_SAMPLING_STATE() TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0) 414 #define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \ 415 TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name) 416 #define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \ 417 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName) 418 419 //////////////////////////////////////////////////////////////////////////////// 420 // Implementation specific tracing API definitions. 421 422 // Get a pointer to the enabled state of the given trace category. Only 423 // long-lived literal strings should be given as the category name. The returned 424 // pointer can be held permanently in a local static for example. If the 425 // unsigned char is non-zero, tracing is enabled. If tracing is enabled, 426 // TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled 427 // between the load of the tracing state and the call to 428 // TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out 429 // for best performance when tracing is disabled. 430 // const unsigned char* 431 // TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name) 432 #define TRACE_EVENT_API_GET_CATEGORY_ENABLED angle::GetTraceCategoryEnabledFlag 433 434 // Add a trace event to the platform tracing system. 435 // void TRACE_EVENT_API_ADD_TRACE_EVENT( 436 // char phase, 437 // const unsigned char* category_enabled, 438 // const char* name, 439 // unsigned long long id, 440 // int num_args, 441 // const char** arg_names, 442 // const unsigned char* arg_types, 443 // const unsigned long long* arg_values, 444 // unsigned char flags) 445 #define TRACE_EVENT_API_ADD_TRACE_EVENT angle::AddTraceEvent 446 447 //////////////////////////////////////////////////////////////////////////////// 448 449 // Implementation detail: trace event macros create temporary variables 450 // to keep instrumentation overhead low. These macros give each temporary 451 // variable a unique name based on the line number to prevent name collissions. 452 #define INTERNAL_TRACE_EVENT_UID3(a, b) trace_event_unique_##a##b 453 #define INTERNAL_TRACE_EVENT_UID2(a, b) INTERNAL_TRACE_EVENT_UID3(a, b) 454 #define INTERNALTRACEEVENTUID(name_prefix) INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__) 455 456 // Implementation detail: internal macro to create static category. 457 #define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, category) \ 458 static const unsigned char *INTERNALTRACEEVENTUID(catstatic) = \ 459 TRACE_EVENT_API_GET_CATEGORY_ENABLED(platform, category); 460 461 // Implementation detail: internal macro to create static category and add 462 // event if the category is enabled. 463 #define INTERNAL_TRACE_EVENT_ADD(platform, phase, category, name, flags, ...) \ 464 do \ 465 { \ 466 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, category); \ 467 if (*INTERNALTRACEEVENTUID(catstatic)) \ 468 { \ 469 gl::TraceEvent::addTraceEvent(platform, phase, INTERNALTRACEEVENTUID(catstatic), name, \ 470 gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \ 471 } \ 472 } while (0) 473 474 // Implementation detail: internal macro to create static category and add begin 475 // event if the category is enabled. Also adds the end event when the scope 476 // ends. 477 #define INTERNAL_TRACE_EVENT_ADD_SCOPED(platform, category, name, ...) \ 478 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, category); \ 479 gl::TraceEvent::TraceEndOnScopeClose INTERNALTRACEEVENTUID(profileScope); \ 480 do \ 481 { \ 482 if (*INTERNALTRACEEVENTUID(catstatic)) \ 483 { \ 484 gl::TraceEvent::addTraceEvent( \ 485 platform, TRACE_EVENT_PHASE_BEGIN, INTERNALTRACEEVENTUID(catstatic), name, \ 486 gl::TraceEvent::noEventId, TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \ 487 INTERNALTRACEEVENTUID(profileScope) \ 488 .initialize(platform, INTERNALTRACEEVENTUID(catstatic), name); \ 489 } \ 490 } while (0) 491 492 // Implementation detail: internal macro to create static category and add 493 // event if the category is enabled. 494 #define INTERNAL_TRACE_EVENT_ADD_WITH_ID(platform, phase, category, name, id, flags, ...) \ 495 do \ 496 { \ 497 INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(platform, category); \ 498 if (*INTERNALTRACEEVENTUID(catstatic)) \ 499 { \ 500 unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \ 501 gl::TraceEvent::TraceID traceEventTraceID(id, &traceEventFlags); \ 502 gl::TraceEvent::addTraceEvent(platform, phase, INTERNALTRACEEVENTUID(catstatic), name, \ 503 traceEventTraceID.data(), traceEventFlags, \ 504 ##__VA_ARGS__); \ 505 } \ 506 } while (0) 507 508 // Notes regarding the following definitions: 509 // New values can be added and propagated to third party libraries, but existing 510 // definitions must never be changed, because third party libraries may use old 511 // definitions. 512 513 // Phase indicates the nature of an event entry. E.g. part of a begin/end pair. 514 #define TRACE_EVENT_PHASE_BEGIN ('B') 515 #define TRACE_EVENT_PHASE_END ('E') 516 #define TRACE_EVENT_PHASE_INSTANT ('I') 517 #define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S') 518 #define TRACE_EVENT_PHASE_ASYNC_STEP ('T') 519 #define TRACE_EVENT_PHASE_ASYNC_END ('F') 520 #define TRACE_EVENT_PHASE_METADATA ('M') 521 #define TRACE_EVENT_PHASE_COUNTER ('C') 522 #define TRACE_EVENT_PHASE_SAMPLE ('P') 523 524 // Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT. 525 #define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0)) 526 #define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0)) 527 #define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1)) 528 #define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2)) 529 530 // Type values for identifying types in the TraceValue union. 531 #define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1)) 532 #define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2)) 533 #define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3)) 534 #define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4)) 535 #define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5)) 536 #define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6)) 537 #define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7)) 538 539 namespace gl 540 { 541 542 namespace TraceEvent 543 { 544 545 // Specify these values when the corresponding argument of addTraceEvent is not 546 // used. 547 const int zeroNumArgs = 0; 548 const unsigned long long noEventId = 0; 549 550 // TraceID encapsulates an ID that can either be an integer or pointer. Pointers 551 // are mangled with the Process ID so that they are unlikely to collide when the 552 // same pointer is used on different processes. 553 class TraceID 554 { 555 public: 556 explicit TraceID(const void *id, unsigned char *flags) 557 : m_data(static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(id))) 558 { 559 *flags |= TRACE_EVENT_FLAG_MANGLE_ID; 560 } 561 explicit TraceID(unsigned long long id, unsigned char *flags) : m_data(id) { (void)flags; } 562 explicit TraceID(unsigned long id, unsigned char *flags) : m_data(id) { (void)flags; } 563 explicit TraceID(unsigned int id, unsigned char *flags) : m_data(id) { (void)flags; } 564 explicit TraceID(unsigned short id, unsigned char *flags) : m_data(id) { (void)flags; } 565 explicit TraceID(unsigned char id, unsigned char *flags) : m_data(id) { (void)flags; } 566 explicit TraceID(long long id, unsigned char *flags) 567 : m_data(static_cast<unsigned long long>(id)) 568 { 569 (void)flags; 570 } 571 explicit TraceID(long id, unsigned char *flags) : m_data(static_cast<unsigned long long>(id)) 572 { 573 (void)flags; 574 } 575 explicit TraceID(int id, unsigned char *flags) : m_data(static_cast<unsigned long long>(id)) 576 { 577 (void)flags; 578 } 579 explicit TraceID(short id, unsigned char *flags) : m_data(static_cast<unsigned long long>(id)) 580 { 581 (void)flags; 582 } 583 explicit TraceID(signed char id, unsigned char *flags) 584 : m_data(static_cast<unsigned long long>(id)) 585 { 586 (void)flags; 587 } 588 589 unsigned long long data() const { return m_data; } 590 591 private: 592 unsigned long long m_data; 593 }; 594 595 // Simple union to store various types as unsigned long long. 596 union TraceValueUnion 597 { 598 bool m_bool; 599 unsigned long long m_uint; 600 long long m_int; 601 double m_double; 602 const void *m_pointer; 603 const char *m_string; 604 }; 605 606 // Simple container for const char* that should be copied instead of retained. 607 class TraceStringWithCopy 608 { 609 public: 610 explicit TraceStringWithCopy(const char *str) : m_str(str) {} 611 operator const char *() const { return m_str; } 612 613 private: 614 const char *m_str; 615 }; 616 617 // Define setTraceValue for each allowed type. It stores the type and 618 // value in the return arguments. This allows this API to avoid declaring any 619 // structures so that it is portable to third_party libraries. 620 #define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, union_member, value_type_id) \ 621 static inline void setTraceValue(actual_type arg, unsigned char *type, \ 622 unsigned long long *value) \ 623 { \ 624 TraceValueUnion typeValue; \ 625 typeValue.union_member = arg; \ 626 *type = value_type_id; \ 627 *value = typeValue.m_uint; \ 628 } 629 // Simpler form for int types that can be safely casted. 630 #define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, value_type_id) \ 631 static inline void setTraceValue(actual_type arg, unsigned char *type, \ 632 unsigned long long *value) \ 633 { \ 634 *type = value_type_id; \ 635 *value = static_cast<unsigned long long>(arg); \ 636 } 637 638 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT) 639 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT) 640 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT) 641 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT) 642 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT) 643 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT) 644 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT) 645 INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT) 646 INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL) 647 INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE) 648 INTERNAL_DECLARE_SET_TRACE_VALUE(const void *, m_pointer, TRACE_VALUE_TYPE_POINTER) 649 INTERNAL_DECLARE_SET_TRACE_VALUE(const char *, m_string, TRACE_VALUE_TYPE_STRING) 650 INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy &, 651 m_string, 652 TRACE_VALUE_TYPE_COPY_STRING) 653 654 #undef INTERNAL_DECLARE_SET_TRACE_VALUE 655 #undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT 656 657 static inline void setTraceValue(const std::string &arg, 658 unsigned char *type, 659 unsigned long long *value) 660 { 661 TraceValueUnion typeValue; 662 typeValue.m_string = arg.data(); 663 *type = TRACE_VALUE_TYPE_COPY_STRING; 664 *value = typeValue.m_uint; 665 } 666 667 // These addTraceEvent template functions are defined here instead of in the 668 // macro, because the arg values could be temporary string objects. In order to 669 // store pointers to the internal c_str and pass through to the tracing API, the 670 // arg values must live throughout these procedures. 671 672 static inline angle::TraceEventHandle addTraceEvent(angle::PlatformMethods *platform, 673 char phase, 674 const unsigned char *categoryEnabled, 675 const char *name, 676 unsigned long long id, 677 unsigned char flags) 678 { 679 return TRACE_EVENT_API_ADD_TRACE_EVENT(platform, phase, categoryEnabled, name, id, zeroNumArgs, 680 0, 0, 0, flags); 681 } 682 683 template <class ARG1_TYPE> 684 static inline angle::TraceEventHandle addTraceEvent(angle::PlatformMethods *platform, 685 char phase, 686 const unsigned char *categoryEnabled, 687 const char *name, 688 unsigned long long id, 689 unsigned char flags, 690 const char *arg1Name, 691 const ARG1_TYPE &arg1Val) 692 { 693 const int numArgs = 1; 694 unsigned char argTypes[1]; 695 unsigned long long argValues[1]; 696 setTraceValue(arg1Val, &argTypes[0], &argValues[0]); 697 return TRACE_EVENT_API_ADD_TRACE_EVENT(platform, phase, categoryEnabled, name, id, numArgs, 698 &arg1Name, argTypes, argValues, flags); 699 } 700 701 template <class ARG1_TYPE, class ARG2_TYPE> 702 static inline angle::TraceEventHandle addTraceEvent(angle::PlatformMethods *platform, 703 char phase, 704 const unsigned char *categoryEnabled, 705 const char *name, 706 unsigned long long id, 707 unsigned char flags, 708 const char *arg1Name, 709 const ARG1_TYPE &arg1Val, 710 const char *arg2Name, 711 const ARG2_TYPE &arg2Val) 712 { 713 const int numArgs = 2; 714 const char *argNames[2] = {arg1Name, arg2Name}; 715 unsigned char argTypes[2]; 716 unsigned long long argValues[2]; 717 setTraceValue(arg1Val, &argTypes[0], &argValues[0]); 718 setTraceValue(arg2Val, &argTypes[1], &argValues[1]); 719 return TRACE_EVENT_API_ADD_TRACE_EVENT(platform, phase, categoryEnabled, name, id, numArgs, 720 argNames, argTypes, argValues, flags); 721 } 722 723 // Used by TRACE_EVENTx macro. Do not use directly. 724 class TraceEndOnScopeClose 725 { 726 public: 727 // Note: members of m_data intentionally left uninitialized. See initialize. 728 TraceEndOnScopeClose() : m_pdata(0) {} 729 ~TraceEndOnScopeClose() 730 { 731 if (m_pdata) 732 addEventIfEnabled(); 733 } 734 735 void initialize(angle::PlatformMethods *platform, 736 const unsigned char *categoryEnabled, 737 const char *name) 738 { 739 m_data.platform = platform; 740 m_data.categoryEnabled = categoryEnabled; 741 m_data.name = name; 742 m_pdata = &m_data; 743 } 744 745 private: 746 // Add the end event if the category is still enabled. 747 void addEventIfEnabled() 748 { 749 // Only called when m_pdata is non-null. 750 if (*m_pdata->categoryEnabled) 751 { 752 TRACE_EVENT_API_ADD_TRACE_EVENT(m_pdata->platform, TRACE_EVENT_PHASE_END, 753 m_pdata->categoryEnabled, m_pdata->name, noEventId, 754 zeroNumArgs, 0, 0, 0, TRACE_EVENT_FLAG_NONE); 755 } 756 } 757 758 // This Data struct workaround is to avoid initializing all the members 759 // in Data during construction of this object, since this object is always 760 // constructed, even when tracing is disabled. If the members of Data were 761 // members of this class instead, compiler warnings occur about potential 762 // uninitialized accesses. 763 struct Data 764 { 765 angle::PlatformMethods *platform; 766 const unsigned char *categoryEnabled; 767 const char *name; 768 }; 769 Data *m_pdata; 770 Data m_data; 771 }; 772 773 } // namespace TraceEvent 774 775 } // namespace gl 776 777 #endif