diff options
author | primiano <primiano@chromium.org> | 2015-06-16 13:56:41 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-06-16 20:57:08 +0000 |
commit | c525abe0b3a3fd9946e8a2db6f8fc251c40ab4d0 (patch) | |
tree | be4c771f0943c5fce3f9714d754f1bbb65ea590f /base | |
parent | 027857bdba4dce9bea91ad4a49c9263e4c37c2f0 (diff) | |
download | chromium_src-c525abe0b3a3fd9946e8a2db6f8fc251c40ab4d0.zip chromium_src-c525abe0b3a3fd9946e8a2db6f8fc251c40ab4d0.tar.gz chromium_src-c525abe0b3a3fd9946e8a2db6f8fc251c40ab4d0.tar.bz2 |
[tracing] Warmup the ThreadLocalEventBuffer when MemoryInfra is enabled
When memory tracing is enabled, the initialization of
ThreadLocalEventBuffer registers its own MemoryDumpProvider to account
for the memory overhead caused by tracing itself.
Before this CL, the ThreadLocalEventBuffer is lazily initialized the
first time a TRACE_EVENT* is called. Doing that w/ MemoryInfra enabled
though could lead to a deadlock if the first TRACE_EVENT happens in
the middle of a memory dump, in which case the ThreadLocalEventBuffer
would try to register a dump provider while dumping.
Races are broken by ensuring that, when a dump provider is being
registered, the ThreadLocalEventBuffer for its thread is being
initialized.
BUG=500569
Review URL: https://codereview.chromium.org/1191473004
Cr-Commit-Position: refs/heads/master@{#334689}
Diffstat (limited to 'base')
-rw-r--r-- | base/trace_event/memory_dump_manager.cc | 25 | ||||
-rw-r--r-- | base/trace_event/trace_event_impl.cc | 42 | ||||
-rw-r--r-- | base/trace_event/trace_event_impl.h | 4 |
3 files changed, 51 insertions, 20 deletions
diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc index e10a77d..82fe10a 100644 --- a/base/trace_event/memory_dump_manager.cc +++ b/base/trace_event/memory_dump_manager.cc @@ -8,6 +8,7 @@ #include "base/atomic_sequence_num.h" #include "base/compiler_specific.h" +#include "base/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_provider.h" #include "base/trace_event/memory_dump_session_state.h" #include "base/trace_event/process_memory_dump.h" @@ -142,6 +143,10 @@ void RequestPeriodicGlobalDump() { MemoryDumpManager::GetInstance()->RequestGlobalDump(dump_type); } +void InitializeThreadLocalEventBufferIfSupported() { + TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); +} + } // namespace // static @@ -285,6 +290,11 @@ void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, bool did_any_provider_dump = false; bool did_post_any_async_task = false; + // Initalizes the ThreadLocalEventBuffer for the syncrhonous dump providers + // that will be invoked in this thread without other posts. The initialization + // for the asynchronous providers, instead, is handled in OnTraceLogEnabled(). + InitializeThreadLocalEventBufferIfSupported(); + // Iterate over the active dump providers and invoke OnMemoryDump(pmd). // The MDM guarantees linearity (at most one MDP is active within one // process) and thread-safety (MDM enforces the right locking when entering / @@ -396,8 +406,19 @@ void MemoryDumpManager::OnTraceLogEnabled() { } session_state_ = new MemoryDumpSessionState(); - for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) - it->second.disabled = false; + for (auto it = dump_providers_.begin(); it != dump_providers_.end(); ++it) { + MemoryDumpProviderInfo& mdp_info = it->second; + mdp_info.disabled = false; + if (mdp_info.task_runner) { + // The thread local event buffer must be initialized at this point as it + // registers its own dump provider (for tracing overhead acounting). + // The registration cannot happen lazily during the first TRACE_EVENT* + // as it might end up registering the ThreadLocalEventBuffer while + // in onMemoryDump(), which will deadlock. + mdp_info.task_runner->PostTask( + FROM_HERE, Bind(&InitializeThreadLocalEventBufferIfSupported)); + } + } subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc index 5882333..f760b88 100644 --- a/base/trace_event/trace_event_impl.cc +++ b/base/trace_event/trace_event_impl.cc @@ -1312,6 +1312,26 @@ TraceLog::TraceLog() TraceLog::~TraceLog() { } +void TraceLog::InitializeThreadLocalEventBufferIfSupported() { + // A ThreadLocalEventBuffer needs the message loop + // - to know when the thread exits; + // - to handle the final flush. + // For a thread without a message loop or the message loop may be blocked, the + // trace events will be added into the main buffer directly. + if (thread_blocks_message_loop_.Get() || !MessageLoop::current()) + return; + auto thread_local_event_buffer = thread_local_event_buffer_.Get(); + if (thread_local_event_buffer && + !CheckGeneration(thread_local_event_buffer->generation())) { + delete thread_local_event_buffer; + thread_local_event_buffer = NULL; + } + if (!thread_local_event_buffer) { + thread_local_event_buffer = new ThreadLocalEventBuffer(this); + thread_local_event_buffer_.Set(thread_local_event_buffer); + } +} + bool TraceLog::OnMemoryDump(ProcessMemoryDump* pmd) { TraceEventMemoryOverhead overhead; overhead.Add("TraceLog", sizeof(*this)); @@ -2003,24 +2023,10 @@ TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp( OffsetNow() : offset_event_timestamp; ThreadTicks thread_now = ThreadNow(); - ThreadLocalEventBuffer* thread_local_event_buffer = NULL; - // A ThreadLocalEventBuffer needs the message loop - // - to know when the thread exits; - // - to handle the final flush. - // For a thread without a message loop or the message loop may be blocked, the - // trace events will be added into the main buffer directly. - if (!thread_blocks_message_loop_.Get() && MessageLoop::current()) { - thread_local_event_buffer = thread_local_event_buffer_.Get(); - if (thread_local_event_buffer && - !CheckGeneration(thread_local_event_buffer->generation())) { - delete thread_local_event_buffer; - thread_local_event_buffer = NULL; - } - if (!thread_local_event_buffer) { - thread_local_event_buffer = new ThreadLocalEventBuffer(this); - thread_local_event_buffer_.Set(thread_local_event_buffer); - } - } + // |thread_local_event_buffer_| can be null if the current thread doesn't have + // a message loop or the message loop is blocked. + InitializeThreadLocalEventBufferIfSupported(); + auto thread_local_event_buffer = thread_local_event_buffer_.Get(); // Check and update the current thread name only if the event is for the // current thread to avoid locks in most cases. diff --git a/base/trace_event/trace_event_impl.h b/base/trace_event/trace_event_impl.h index 503a69d..2922840 100644 --- a/base/trace_event/trace_event_impl.h +++ b/base/trace_event/trace_event_impl.h @@ -334,6 +334,10 @@ class BASE_EXPORT TraceLog : public MemoryDumpProvider { // Retrieves a copy (for thread-safety) of the current TraceConfig. TraceConfig GetCurrentTraceConfig() const; + // Initializes the thread-local event buffer, if not already initialized and + // if the current thread supports that (has a message loop). + void InitializeThreadLocalEventBufferIfSupported(); + // Enables normal tracing (recording trace events in the trace buffer). // See TraceConfig comments for details on how to control what categories // will be traced. If tracing has already been enabled, |category_filter| will |