| 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() {
|
|
|