| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/trace_event/trace_log.h" | 5 #include "base/trace_event/trace_log.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 | 9 |
| 10 #include "base/base_switches.h" | 10 #include "base/base_switches.h" |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 static_assert( | 72 static_assert( |
| 73 kTraceEventVectorBufferChunks <= TraceBufferChunk::kMaxChunkIndex, | 73 kTraceEventVectorBufferChunks <= TraceBufferChunk::kMaxChunkIndex, |
| 74 "Too many vector buffer chunks"); | 74 "Too many vector buffer chunks"); |
| 75 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; | 75 const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4; |
| 76 | 76 |
| 77 // Can store results for 30 seconds with 1 ms sampling interval. | 77 // Can store results for 30 seconds with 1 ms sampling interval. |
| 78 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize; | 78 const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize; |
| 79 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. | 79 // ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events. |
| 80 const size_t kEchoToConsoleTraceEventBufferChunks = 256; | 80 const size_t kEchoToConsoleTraceEventBufferChunks = 256; |
| 81 | 81 |
| 82 // The overhead of TraceEvent above this threshold will be reported in the | |
| 83 // trace. | |
| 84 const int kOverheadReportThresholdInMicroseconds = 50; | |
| 85 const size_t kTraceEventBufferSizeInBytes = 100 * 1024; | 82 const size_t kTraceEventBufferSizeInBytes = 100 * 1024; |
| 86 const int kThreadFlushTimeoutMs = 3000; | 83 const int kThreadFlushTimeoutMs = 3000; |
| 87 | 84 |
| 88 #if !defined(OS_NACL) | 85 #if !defined(OS_NACL) |
| 89 // These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575. | 86 // These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575. |
| 90 const char kEchoToConsoleCategoryFilter[] = "-ipc,-task"; | 87 const char kEchoToConsoleCategoryFilter[] = "-ipc,-task"; |
| 91 #endif | 88 #endif |
| 92 | 89 |
| 93 #define MAX_CATEGORY_GROUPS 100 | 90 #define MAX_CATEGORY_GROUPS 100 |
| 94 | 91 |
| 95 // Parallel arrays g_category_groups and g_category_group_enabled are separate | 92 // Parallel arrays g_category_groups and g_category_group_enabled are separate |
| 96 // so that a pointer to a member of g_category_group_enabled can be easily | 93 // so that a pointer to a member of g_category_group_enabled can be easily |
| 97 // converted to an index into g_category_groups. This allows macros to deal | 94 // converted to an index into g_category_groups. This allows macros to deal |
| 98 // only with char enabled pointers from g_category_group_enabled, and we can | 95 // only with char enabled pointers from g_category_group_enabled, and we can |
| 99 // convert internally to determine the category name from the char enabled | 96 // convert internally to determine the category name from the char enabled |
| 100 // pointer. | 97 // pointer. |
| 101 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { | 98 const char* g_category_groups[MAX_CATEGORY_GROUPS] = { |
| 102 "toplevel", | 99 "toplevel", |
| 103 "tracing already shutdown", | 100 "tracing already shutdown", |
| 104 "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS", | 101 "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS", |
| 105 "__metadata", | 102 "__metadata"}; |
| 106 // For reporting trace_event overhead. For thread local event buffers only. | |
| 107 "trace_event_overhead"}; | |
| 108 | 103 |
| 109 // The enabled flag is char instead of bool so that the API can be used from C. | 104 // The enabled flag is char instead of bool so that the API can be used from C. |
| 110 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = {0}; | 105 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = {0}; |
| 111 // Indexes here have to match the g_category_groups array indexes above. | 106 // Indexes here have to match the g_category_groups array indexes above. |
| 112 const int g_category_already_shutdown = 1; | 107 const int g_category_already_shutdown = 1; |
| 113 const int g_category_categories_exhausted = 2; | 108 const int g_category_categories_exhausted = 2; |
| 114 const int g_category_metadata = 3; | 109 const int g_category_metadata = 3; |
| 115 const int g_category_trace_event_overhead = 4; | 110 const int g_num_builtin_categories = 4; |
| 116 const int g_num_builtin_categories = 5; | |
| 117 // Skip default categories. | 111 // Skip default categories. |
| 118 base::subtle::AtomicWord g_category_index = g_num_builtin_categories; | 112 base::subtle::AtomicWord g_category_index = g_num_builtin_categories; |
| 119 | 113 |
| 120 // The name of the current thread. This is used to decide if the current | 114 // The name of the current thread. This is used to decide if the current |
| 121 // thread name has changed. We combine all the seen thread names into the | 115 // thread name has changed. We combine all the seen thread names into the |
| 122 // output name for the thread. | 116 // output name for the thread. |
| 123 LazyInstance<ThreadLocalPointer<const char>>::Leaky g_current_thread_name = | 117 LazyInstance<ThreadLocalPointer<const char>>::Leaky g_current_thread_name = |
| 124 LAZY_INSTANCE_INITIALIZER; | 118 LAZY_INSTANCE_INITIALIZER; |
| 125 | 119 |
| 126 ThreadTicks ThreadNow() { | 120 ThreadTicks ThreadNow() { |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 | 208 |
| 215 class TraceLog::ThreadLocalEventBuffer | 209 class TraceLog::ThreadLocalEventBuffer |
| 216 : public MessageLoop::DestructionObserver, | 210 : public MessageLoop::DestructionObserver, |
| 217 public MemoryDumpProvider { | 211 public MemoryDumpProvider { |
| 218 public: | 212 public: |
| 219 ThreadLocalEventBuffer(TraceLog* trace_log); | 213 ThreadLocalEventBuffer(TraceLog* trace_log); |
| 220 ~ThreadLocalEventBuffer() override; | 214 ~ThreadLocalEventBuffer() override; |
| 221 | 215 |
| 222 TraceEvent* AddTraceEvent(TraceEventHandle* handle); | 216 TraceEvent* AddTraceEvent(TraceEventHandle* handle); |
| 223 | 217 |
| 224 void ReportOverhead(const TraceTicks& event_timestamp, | |
| 225 const ThreadTicks& event_thread_timestamp); | |
| 226 | |
| 227 TraceEvent* GetEventByHandle(TraceEventHandle handle) { | 218 TraceEvent* GetEventByHandle(TraceEventHandle handle) { |
| 228 if (!chunk_ || handle.chunk_seq != chunk_->seq() || | 219 if (!chunk_ || handle.chunk_seq != chunk_->seq() || |
| 229 handle.chunk_index != chunk_index_) | 220 handle.chunk_index != chunk_index_) |
| 230 return NULL; | 221 return NULL; |
| 231 | 222 |
| 232 return chunk_->GetEventAt(handle.event_index); | 223 return chunk_->GetEventAt(handle.event_index); |
| 233 } | 224 } |
| 234 | 225 |
| 235 int generation() const { return generation_; } | 226 int generation() const { return generation_; } |
| 236 | 227 |
| 237 private: | 228 private: |
| 238 // MessageLoop::DestructionObserver | 229 // MessageLoop::DestructionObserver |
| 239 void WillDestroyCurrentMessageLoop() override; | 230 void WillDestroyCurrentMessageLoop() override; |
| 240 | 231 |
| 241 // MemoryDumpProvider implementation. | 232 // MemoryDumpProvider implementation. |
| 242 bool OnMemoryDump(const MemoryDumpArgs& args, | 233 bool OnMemoryDump(const MemoryDumpArgs& args, |
| 243 ProcessMemoryDump* pmd) override; | 234 ProcessMemoryDump* pmd) override; |
| 244 | 235 |
| 245 void FlushWhileLocked(); | 236 void FlushWhileLocked(); |
| 246 | 237 |
| 247 void CheckThisIsCurrentBuffer() const { | 238 void CheckThisIsCurrentBuffer() const { |
| 248 DCHECK(trace_log_->thread_local_event_buffer_.Get() == this); | 239 DCHECK(trace_log_->thread_local_event_buffer_.Get() == this); |
| 249 } | 240 } |
| 250 | 241 |
| 251 // Since TraceLog is a leaky singleton, trace_log_ will always be valid | 242 // Since TraceLog is a leaky singleton, trace_log_ will always be valid |
| 252 // as long as the thread exists. | 243 // as long as the thread exists. |
| 253 TraceLog* trace_log_; | 244 TraceLog* trace_log_; |
| 254 scoped_ptr<TraceBufferChunk> chunk_; | 245 scoped_ptr<TraceBufferChunk> chunk_; |
| 255 size_t chunk_index_; | 246 size_t chunk_index_; |
| 256 int event_count_; | |
| 257 TimeDelta overhead_; | |
| 258 int generation_; | 247 int generation_; |
| 259 | 248 |
| 260 DISALLOW_COPY_AND_ASSIGN(ThreadLocalEventBuffer); | 249 DISALLOW_COPY_AND_ASSIGN(ThreadLocalEventBuffer); |
| 261 }; | 250 }; |
| 262 | 251 |
| 263 TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log) | 252 TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log) |
| 264 : trace_log_(trace_log), | 253 : trace_log_(trace_log), |
| 265 chunk_index_(0), | 254 chunk_index_(0), |
| 266 event_count_(0), | |
| 267 generation_(trace_log->generation()) { | 255 generation_(trace_log->generation()) { |
| 268 // ThreadLocalEventBuffer is created only if the thread has a message loop, so | 256 // ThreadLocalEventBuffer is created only if the thread has a message loop, so |
| 269 // the following message_loop won't be NULL. | 257 // the following message_loop won't be NULL. |
| 270 MessageLoop* message_loop = MessageLoop::current(); | 258 MessageLoop* message_loop = MessageLoop::current(); |
| 271 message_loop->AddDestructionObserver(this); | 259 message_loop->AddDestructionObserver(this); |
| 272 | 260 |
| 273 // This is to report the local memory usage when memory-infra is enabled. | 261 // This is to report the local memory usage when memory-infra is enabled. |
| 274 MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 262 MemoryDumpManager::GetInstance()->RegisterDumpProvider( |
| 275 this, ThreadTaskRunnerHandle::Get()); | 263 this, ThreadTaskRunnerHandle::Get()); |
| 276 | 264 |
| 277 AutoLock lock(trace_log->lock_); | 265 AutoLock lock(trace_log->lock_); |
| 278 trace_log->thread_message_loops_.insert(message_loop); | 266 trace_log->thread_message_loops_.insert(message_loop); |
| 279 } | 267 } |
| 280 | 268 |
| 281 TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() { | 269 TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() { |
| 282 CheckThisIsCurrentBuffer(); | 270 CheckThisIsCurrentBuffer(); |
| 283 MessageLoop::current()->RemoveDestructionObserver(this); | 271 MessageLoop::current()->RemoveDestructionObserver(this); |
| 284 MemoryDumpManager::GetInstance()->UnregisterDumpProvider(this); | 272 MemoryDumpManager::GetInstance()->UnregisterDumpProvider(this); |
| 285 | 273 |
| 286 // Zero event_count_ happens in either of the following cases: | |
| 287 // - no event generated for the thread; | |
| 288 // - the thread has no message loop; | |
| 289 // - trace_event_overhead is disabled. | |
| 290 if (event_count_) { | |
| 291 InitializeMetadataEvent(AddTraceEvent(NULL), | |
| 292 static_cast<int>(base::PlatformThread::CurrentId()), | |
| 293 "overhead", "average_overhead", | |
| 294 overhead_.InMillisecondsF() / event_count_); | |
| 295 } | |
| 296 | |
| 297 { | 274 { |
| 298 AutoLock lock(trace_log_->lock_); | 275 AutoLock lock(trace_log_->lock_); |
| 299 FlushWhileLocked(); | 276 FlushWhileLocked(); |
| 300 trace_log_->thread_message_loops_.erase(MessageLoop::current()); | 277 trace_log_->thread_message_loops_.erase(MessageLoop::current()); |
| 301 } | 278 } |
| 302 trace_log_->thread_local_event_buffer_.Set(NULL); | 279 trace_log_->thread_local_event_buffer_.Set(NULL); |
| 303 } | 280 } |
| 304 | 281 |
| 305 TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent( | 282 TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent( |
| 306 TraceEventHandle* handle) { | 283 TraceEventHandle* handle) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 320 return NULL; | 297 return NULL; |
| 321 | 298 |
| 322 size_t event_index; | 299 size_t event_index; |
| 323 TraceEvent* trace_event = chunk_->AddTraceEvent(&event_index); | 300 TraceEvent* trace_event = chunk_->AddTraceEvent(&event_index); |
| 324 if (trace_event && handle) | 301 if (trace_event && handle) |
| 325 MakeHandle(chunk_->seq(), chunk_index_, event_index, handle); | 302 MakeHandle(chunk_->seq(), chunk_index_, event_index, handle); |
| 326 | 303 |
| 327 return trace_event; | 304 return trace_event; |
| 328 } | 305 } |
| 329 | 306 |
| 330 void TraceLog::ThreadLocalEventBuffer::ReportOverhead( | |
| 331 const TraceTicks& event_timestamp, | |
| 332 const ThreadTicks& event_thread_timestamp) { | |
| 333 if (!g_category_group_enabled[g_category_trace_event_overhead]) | |
| 334 return; | |
| 335 | |
| 336 CheckThisIsCurrentBuffer(); | |
| 337 | |
| 338 event_count_++; | |
| 339 ThreadTicks thread_now = ThreadNow(); | |
| 340 TraceTicks now = trace_log_->OffsetNow(); | |
| 341 TimeDelta overhead = now - event_timestamp; | |
| 342 if (overhead.InMicroseconds() >= kOverheadReportThresholdInMicroseconds) { | |
| 343 TraceEvent* trace_event = AddTraceEvent(NULL); | |
| 344 if (trace_event) { | |
| 345 trace_event->Initialize( | |
| 346 static_cast<int>(PlatformThread::CurrentId()), | |
| 347 event_timestamp, | |
| 348 event_thread_timestamp, | |
| 349 TRACE_EVENT_PHASE_COMPLETE, | |
| 350 &g_category_group_enabled[g_category_trace_event_overhead], | |
| 351 "overhead", | |
| 352 trace_event_internal::kNoId, // id | |
| 353 trace_event_internal::kNoId, // context_id | |
| 354 trace_event_internal::kNoId, // bind_id | |
| 355 ::trace_event_internal::kZeroNumArgs, | |
| 356 nullptr, | |
| 357 nullptr, | |
| 358 nullptr, | |
| 359 nullptr, | |
| 360 TRACE_EVENT_FLAG_NONE); | |
| 361 trace_event->UpdateDuration(now, thread_now); | |
| 362 } | |
| 363 } | |
| 364 overhead_ += overhead; | |
| 365 } | |
| 366 | |
| 367 void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() { | 307 void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() { |
| 368 delete this; | 308 delete this; |
| 369 } | 309 } |
| 370 | 310 |
| 371 bool TraceLog::ThreadLocalEventBuffer::OnMemoryDump(const MemoryDumpArgs& args, | 311 bool TraceLog::ThreadLocalEventBuffer::OnMemoryDump(const MemoryDumpArgs& args, |
| 372 ProcessMemoryDump* pmd) { | 312 ProcessMemoryDump* pmd) { |
| 373 if (!chunk_) | 313 if (!chunk_) |
| 374 return true; | 314 return true; |
| 375 std::string dump_base_name = StringPrintf( | 315 std::string dump_base_name = StringPrintf( |
| 376 "tracing/thread_%d", static_cast<int>(PlatformThread::CurrentId())); | 316 "tracing/thread_%d", static_cast<int>(PlatformThread::CurrentId())); |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 627 } else { | 567 } else { |
| 628 category_group_enabled = | 568 category_group_enabled = |
| 629 &g_category_group_enabled[g_category_categories_exhausted]; | 569 &g_category_group_enabled[g_category_categories_exhausted]; |
| 630 } | 570 } |
| 631 return category_group_enabled; | 571 return category_group_enabled; |
| 632 } | 572 } |
| 633 | 573 |
| 634 void TraceLog::GetKnownCategoryGroups( | 574 void TraceLog::GetKnownCategoryGroups( |
| 635 std::vector<std::string>* category_groups) { | 575 std::vector<std::string>* category_groups) { |
| 636 AutoLock lock(lock_); | 576 AutoLock lock(lock_); |
| 637 category_groups->push_back( | |
| 638 g_category_groups[g_category_trace_event_overhead]); | |
| 639 size_t category_index = base::subtle::NoBarrier_Load(&g_category_index); | 577 size_t category_index = base::subtle::NoBarrier_Load(&g_category_index); |
| 640 for (size_t i = g_num_builtin_categories; i < category_index; i++) | 578 for (size_t i = g_num_builtin_categories; i < category_index; i++) |
| 641 category_groups->push_back(g_category_groups[i]); | 579 category_groups->push_back(g_category_groups[i]); |
| 642 } | 580 } |
| 643 | 581 |
| 644 void TraceLog::SetEnabled(const TraceConfig& trace_config, Mode mode) { | 582 void TraceLog::SetEnabled(const TraceConfig& trace_config, Mode mode) { |
| 645 std::vector<EnabledStateObserver*> observer_list; | 583 std::vector<EnabledStateObserver*> observer_list; |
| 646 { | 584 { |
| 647 AutoLock lock(lock_); | 585 AutoLock lock(lock_); |
| 648 | 586 |
| (...skipping 601 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1250 DCHECK(!timestamp.is_null()); | 1188 DCHECK(!timestamp.is_null()); |
| 1251 | 1189 |
| 1252 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) { | 1190 if (flags & TRACE_EVENT_FLAG_MANGLE_ID) { |
| 1253 if ((flags & TRACE_EVENT_FLAG_FLOW_IN) || | 1191 if ((flags & TRACE_EVENT_FLAG_FLOW_IN) || |
| 1254 (flags & TRACE_EVENT_FLAG_FLOW_OUT)) | 1192 (flags & TRACE_EVENT_FLAG_FLOW_OUT)) |
| 1255 bind_id = MangleEventId(bind_id); | 1193 bind_id = MangleEventId(bind_id); |
| 1256 id = MangleEventId(id); | 1194 id = MangleEventId(id); |
| 1257 } | 1195 } |
| 1258 | 1196 |
| 1259 TraceTicks offset_event_timestamp = OffsetTimestamp(timestamp); | 1197 TraceTicks offset_event_timestamp = OffsetTimestamp(timestamp); |
| 1260 TraceTicks now = flags & TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP | |
| 1261 ? OffsetNow() | |
| 1262 : offset_event_timestamp; | |
| 1263 ThreadTicks thread_now = ThreadNow(); | 1198 ThreadTicks thread_now = ThreadNow(); |
| 1264 | 1199 |
| 1265 // |thread_local_event_buffer_| can be null if the current thread doesn't have | 1200 // |thread_local_event_buffer_| can be null if the current thread doesn't have |
| 1266 // a message loop or the message loop is blocked. | 1201 // a message loop or the message loop is blocked. |
| 1267 InitializeThreadLocalEventBufferIfSupported(); | 1202 InitializeThreadLocalEventBufferIfSupported(); |
| 1268 auto thread_local_event_buffer = thread_local_event_buffer_.Get(); | 1203 auto thread_local_event_buffer = thread_local_event_buffer_.Get(); |
| 1269 | 1204 |
| 1270 // Check and update the current thread name only if the event is for the | 1205 // Check and update the current thread name only if the event is for the |
| 1271 // current thread to avoid locks in most cases. | 1206 // current thread to avoid locks in most cases. |
| 1272 if (thread_id == static_cast<int>(PlatformThread::CurrentId())) { | 1207 if (thread_id == static_cast<int>(PlatformThread::CurrentId())) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1378 subtle::NoBarrier_Load(&event_callback_)); | 1313 subtle::NoBarrier_Load(&event_callback_)); |
| 1379 if (event_callback) { | 1314 if (event_callback) { |
| 1380 event_callback( | 1315 event_callback( |
| 1381 offset_event_timestamp, | 1316 offset_event_timestamp, |
| 1382 phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase, | 1317 phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase, |
| 1383 category_group_enabled, name, id, num_args, arg_names, arg_types, | 1318 category_group_enabled, name, id, num_args, arg_names, arg_types, |
| 1384 arg_values, flags); | 1319 arg_values, flags); |
| 1385 } | 1320 } |
| 1386 } | 1321 } |
| 1387 | 1322 |
| 1388 if (thread_local_event_buffer) | |
| 1389 thread_local_event_buffer->ReportOverhead(now, thread_now); | |
| 1390 | |
| 1391 return handle; | 1323 return handle; |
| 1392 } | 1324 } |
| 1393 | 1325 |
| 1394 // May be called when a COMPELETE event ends and the unfinished event has been | 1326 // May be called when a COMPELETE event ends and the unfinished event has been |
| 1395 // recycled (phase == TRACE_EVENT_PHASE_END and trace_event == NULL). | 1327 // recycled (phase == TRACE_EVENT_PHASE_END and trace_event == NULL). |
| 1396 std::string TraceLog::EventToConsoleMessage(unsigned char phase, | 1328 std::string TraceLog::EventToConsoleMessage(unsigned char phase, |
| 1397 const TraceTicks& timestamp, | 1329 const TraceTicks& timestamp, |
| 1398 TraceEvent* trace_event) { | 1330 TraceEvent* trace_event) { |
| 1399 AutoLock thread_info_lock(thread_info_lock_); | 1331 AutoLock thread_info_lock(thread_info_lock_); |
| 1400 | 1332 |
| (...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1772 } | 1704 } |
| 1773 | 1705 |
| 1774 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 1706 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
| 1775 if (*category_group_enabled_) { | 1707 if (*category_group_enabled_) { |
| 1776 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_, | 1708 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, name_, |
| 1777 event_handle_); | 1709 event_handle_); |
| 1778 } | 1710 } |
| 1779 } | 1711 } |
| 1780 | 1712 |
| 1781 } // namespace trace_event_internal | 1713 } // namespace trace_event_internal |
| OLD | NEW |