Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2831)

Unified Diff: base/trace_event/trace_log.cc

Issue 2503473002: tracing: split out ThreadLocalEventBuffer
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « base/trace_event/trace_log.h ('k') | tools/gn/bootstrap/bootstrap.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/trace_event/trace_log.cc
diff --git a/base/trace_event/trace_log.cc b/base/trace_event/trace_log.cc
index 75af14abed9e4ec38c0c4c2232c4eaed0635c474..67b7a53ae6fd17b5e8dc41bb88336d828f271d96 100644
--- a/base/trace_event/trace_log.cc
+++ b/base/trace_event/trace_log.cc
@@ -40,6 +40,7 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_provider.h"
#include "base/trace_event/process_memory_dump.h"
+#include "base/trace_event/thread_local_event_buffer.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_synthetic_delay.h"
@@ -142,21 +143,6 @@ class AutoThreadLocalBoolean {
DISALLOW_COPY_AND_ASSIGN(AutoThreadLocalBoolean);
};
-// Use this function instead of TraceEventHandle constructor to keep the
-// overhead of ScopedTracer (trace_event.h) constructor minimum.
-void MakeHandle(uint32_t chunk_seq,
- size_t chunk_index,
- size_t event_index,
- TraceEventHandle* handle) {
- DCHECK(chunk_seq);
- DCHECK(chunk_index <= TraceBufferChunk::kMaxChunkIndex);
- DCHECK(event_index < TraceBufferChunk::kTraceBufferChunkSize);
- DCHECK(chunk_index <= std::numeric_limits<uint16_t>::max());
- handle->chunk_seq = chunk_seq;
- handle->chunk_index = static_cast<uint16_t>(chunk_index);
- handle->event_index = static_cast<uint16_t>(event_index);
-}
-
template <typename Function>
void ForEachCategoryFilter(const unsigned char* category_group_enabled,
Function filter_fn) {
@@ -194,143 +180,35 @@ class TraceLog::OptionalAutoLock {
DISALLOW_COPY_AND_ASSIGN(OptionalAutoLock);
};
-class TraceLog::ThreadLocalEventBuffer
- : public MessageLoop::DestructionObserver,
- public MemoryDumpProvider {
- public:
- explicit ThreadLocalEventBuffer(TraceLog* trace_log);
- ~ThreadLocalEventBuffer() override;
-
- TraceEvent* AddTraceEvent(TraceEventHandle* handle);
-
- TraceEvent* GetEventByHandle(TraceEventHandle handle) {
- if (!chunk_ || handle.chunk_seq != chunk_->seq() ||
- handle.chunk_index != chunk_index_) {
- return nullptr;
- }
-
- return chunk_->GetEventAt(handle.event_index);
- }
-
- int generation() const { return generation_; }
-
- private:
- // MessageLoop::DestructionObserver
- void WillDestroyCurrentMessageLoop() override;
-
- // MemoryDumpProvider implementation.
- bool OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) override;
-
- void FlushWhileLocked();
-
- void CheckThisIsCurrentBuffer() const {
- DCHECK(trace_log_->thread_local_event_buffer_.Get() == this);
- }
-
- // Since TraceLog is a leaky singleton, trace_log_ will always be valid
- // as long as the thread exists.
- TraceLog* trace_log_;
- std::unique_ptr<TraceBufferChunk> chunk_;
- size_t chunk_index_;
- int generation_;
+struct TraceLog::RegisteredAsyncObserver {
+ explicit RegisteredAsyncObserver(WeakPtr<AsyncEnabledStateObserver> observer)
+ : observer(observer), task_runner(ThreadTaskRunnerHandle::Get()) {}
+ ~RegisteredAsyncObserver() {}
- DISALLOW_COPY_AND_ASSIGN(ThreadLocalEventBuffer);
+ WeakPtr<AsyncEnabledStateObserver> observer;
+ scoped_refptr<SequencedTaskRunner> task_runner;
};
-TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log)
- : trace_log_(trace_log),
- chunk_index_(0),
- generation_(trace_log->generation()) {
- // ThreadLocalEventBuffer is created only if the thread has a message loop, so
- // the following message_loop won't be NULL.
- MessageLoop* message_loop = MessageLoop::current();
- message_loop->AddDestructionObserver(this);
-
- // This is to report the local memory usage when memory-infra is enabled.
- MemoryDumpManager::GetInstance()->RegisterDumpProvider(
- this, "ThreadLocalEventBuffer", ThreadTaskRunnerHandle::Get());
-
- AutoLock lock(trace_log->lock_);
- trace_log->thread_message_loops_.insert(message_loop);
-}
-
-TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() {
- CheckThisIsCurrentBuffer();
- MessageLoop::current()->RemoveDestructionObserver(this);
- MemoryDumpManager::GetInstance()->UnregisterDumpProvider(this);
-
- {
- AutoLock lock(trace_log_->lock_);
- FlushWhileLocked();
- trace_log_->thread_message_loops_.erase(MessageLoop::current());
- }
- trace_log_->thread_local_event_buffer_.Set(NULL);
-}
-
-TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent(
- TraceEventHandle* handle) {
- CheckThisIsCurrentBuffer();
+TraceLog::MemoryDumpProviderForThreadLocalBuffer::
+ MemoryDumpProviderForThreadLocalBuffer(
+ ThreadLocalEventBuffer* thread_local_event_buffer)
+ : thread_local_event_buffer_(thread_local_event_buffer) {}
- if (chunk_ && chunk_->IsFull()) {
- AutoLock lock(trace_log_->lock_);
- FlushWhileLocked();
- chunk_.reset();
- }
- if (!chunk_) {
- AutoLock lock(trace_log_->lock_);
- chunk_ = trace_log_->logged_events_->GetChunk(&chunk_index_);
- trace_log_->CheckIfBufferIsFullWhileLocked();
- }
- if (!chunk_)
- return NULL;
-
- size_t event_index;
- TraceEvent* trace_event = chunk_->AddTraceEvent(&event_index);
- if (trace_event && handle)
- MakeHandle(chunk_->seq(), chunk_index_, event_index, handle);
+TraceLog::MemoryDumpProviderForThreadLocalBuffer::
+ ~MemoryDumpProviderForThreadLocalBuffer() {}
- return trace_event;
-}
-
-void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() {
- delete this;
-}
-
-bool TraceLog::ThreadLocalEventBuffer::OnMemoryDump(const MemoryDumpArgs& args,
- ProcessMemoryDump* pmd) {
- if (!chunk_)
- return true;
+bool TraceLog::MemoryDumpProviderForThreadLocalBuffer::OnMemoryDump(
+ const MemoryDumpArgs& args,
+ ProcessMemoryDump* pmd) {
std::string dump_base_name = StringPrintf(
"tracing/thread_%d", static_cast<int>(PlatformThread::CurrentId()));
TraceEventMemoryOverhead overhead;
- chunk_->EstimateTraceMemoryOverhead(&overhead);
+ TraceBufferChunk* const chunk = thread_local_event_buffer_->chunk();
+ chunk->EstimateTraceMemoryOverhead(&overhead);
overhead.DumpInto(dump_base_name.c_str(), pmd);
return true;
}
-void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() {
- if (!chunk_)
- return;
-
- trace_log_->lock_.AssertAcquired();
- if (trace_log_->CheckGeneration(generation_)) {
- // Return the chunk to the buffer only if the generation matches.
- trace_log_->logged_events_->ReturnChunk(chunk_index_, std::move(chunk_));
- }
- // Otherwise this method may be called from the destructor, or TraceLog will
- // find the generation mismatch and delete this buffer soon.
-}
-
-struct TraceLog::RegisteredAsyncObserver {
- explicit RegisteredAsyncObserver(WeakPtr<AsyncEnabledStateObserver> observer)
- : observer(observer), task_runner(ThreadTaskRunnerHandle::Get()) {}
- ~RegisteredAsyncObserver() {}
-
- WeakPtr<AsyncEnabledStateObserver> observer;
- scoped_refptr<SequencedTaskRunner> task_runner;
-};
-
TraceLogStatus::TraceLogStatus() : event_capacity(0), event_count(0) {}
TraceLogStatus::~TraceLogStatus() {}
@@ -374,21 +252,62 @@ void TraceLog::InitializeThreadLocalEventBufferIfSupported() {
// - 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())
+ MessageLoop* const message_loop = MessageLoop::current();
+ if (thread_blocks_message_loop_.Get() || !message_loop)
return;
- HEAP_PROFILER_SCOPED_IGNORE;
+
+ // If the thread-local instance was created during a prior tracing session,
+ // tear it down and re-create it.
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;
+ DestroyThreadLocalEventBufferIfSupported();
+ thread_local_event_buffer = nullptr;
}
if (!thread_local_event_buffer) {
- thread_local_event_buffer = new ThreadLocalEventBuffer(this);
+ HEAP_PROFILER_SCOPED_IGNORE;
+ thread_local_event_buffer = new ThreadLocalEventBuffer(generation());
thread_local_event_buffer_.Set(thread_local_event_buffer);
+ message_loop->AddDestructionObserver(this);
+ // This is to report the local memory usage when memory-infra is enabled.
+ auto memory_dump_provider =
+ MakeUnique<MemoryDumpProviderForThreadLocalBuffer>(
+ thread_local_event_buffer);
+ MemoryDumpManager::GetInstance()->RegisterDumpProvider(
+ memory_dump_provider.get(), "ThreadLocalEventBuffer",
+ message_loop->task_runner());
+ AutoLock lock(lock_);
+ thread_message_loops_.insert(message_loop);
+ thread_local_mdps_[message_loop] = std::move(memory_dump_provider);
}
}
+void TraceLog::DestroyThreadLocalEventBufferIfSupported() {
+ auto* thread_local_event_buffer = thread_local_event_buffer_.Get();
+ if (!thread_local_event_buffer)
+ return;
+ HEAP_PROFILER_SCOPED_IGNORE;
+ thread_local_event_buffer->Flush();
+ thread_local_event_buffer_.Set(nullptr);
+ MessageLoop* const message_loop = MessageLoop::current();
+ delete thread_local_event_buffer;
+ message_loop->RemoveDestructionObserver(this);
+
+ AutoLock lock(lock_);
+ thread_message_loops_.erase(message_loop);
+ auto memory_dump_provider_it = thread_local_mdps_.find(message_loop);
+ DCHECK(memory_dump_provider_it != thread_local_mdps_.end());
+ MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ memory_dump_provider_it->second.get());
+ memory_dump_provider_it->second.reset();
+ thread_local_mdps_.erase(memory_dump_provider_it);
+ // TODO order of this !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+}
+
+void TraceLog::WillDestroyCurrentMessageLoop() {
+ DestroyThreadLocalEventBufferIfSupported();
+}
+
bool TraceLog::OnMemoryDump(const MemoryDumpArgs& args,
ProcessMemoryDump* pmd) {
// TODO(ssid): Use MemoryDumpArgs to create light dumps when requested
@@ -804,9 +723,10 @@ TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
size_t event_index;
TraceEvent* trace_event = thread_shared_chunk_->AddTraceEvent(&event_index);
- if (trace_event && handle) {
- MakeHandle(thread_shared_chunk_->seq(), thread_shared_chunk_index_,
- event_index, handle);
+ DCHECK(trace_event);
+ if (handle) {
+ thread_shared_chunk_->MakeHandle(thread_shared_chunk_index_, event_index,
+ handle);
}
return trace_event;
}
@@ -980,8 +900,7 @@ void TraceLog::FlushCurrentThread(int generation, bool discard_events) {
}
}
- // This will flush the thread local buffer.
- delete thread_local_event_buffer_.Get();
+ DestroyThreadLocalEventBufferIfSupported();
AutoLock lock(lock_);
if (!CheckGeneration(generation) || !flush_task_runner_ ||
@@ -1331,6 +1250,22 @@ void TraceLog::AddMetadataEvent(
metadata_events_.push_back(std::move(trace_event));
}
+std::unique_ptr<TraceBufferChunk> TraceLog::TakeChunk(size_t* chunk_index) {
+ AutoLock lock(lock_);
+ auto chunk = logged_events_->GetChunk(chunk_index);
+ CheckIfBufferIsFullWhileLocked();
+ return chunk;
+}
+
+void TraceLog::ReturnChunk(std::unique_ptr<TraceBufferChunk> chunk,
+ int generation,
+ size_t chunk_index) {
+ AutoLock lock(lock_);
+ // Return the chunk to the buffer only if the generation matches.
+ if (CheckGeneration(generation))
+ logged_events_->ReturnChunk(chunk_index, std::move(chunk));
+}
+
// May be called when a COMPELETE event ends and the unfinished event has been
// recycled (phase == TRACE_EVENT_PHASE_END and trace_event == NULL).
std::string TraceLog::EventToConsoleMessage(unsigned char phase,
@@ -1612,8 +1547,7 @@ size_t TraceLog::GetObserverCountForTest() const {
void TraceLog::SetCurrentThreadBlocksMessageLoop() {
thread_blocks_message_loop_.Set(true);
- // This will flush the thread local buffer.
- delete thread_local_event_buffer_.Get();
+ DestroyThreadLocalEventBufferIfSupported();
}
TraceBuffer* TraceLog::CreateTraceBuffer() {
« no previous file with comments | « base/trace_event/trace_log.h ('k') | tools/gn/bootstrap/bootstrap.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698