diff options
Diffstat (limited to 'base/debug/trace_event_impl.cc')
-rw-r--r-- | base/debug/trace_event_impl.cc | 136 |
1 files changed, 97 insertions, 39 deletions
diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc index 42c6d84..9ee9fc8 100644 --- a/base/debug/trace_event_impl.cc +++ b/base/debug/trace_event_impl.cc @@ -61,6 +61,8 @@ const size_t kTraceEventRingBufferSize = kTraceEventVectorBufferSize / 4; const size_t kTraceEventThreadLocalBufferSize = 64; const size_t kTraceEventBatchSize = 1000; const size_t kTraceEventInitialBufferSize = 1024; +// Can store results for 30 seconds with 1 ms sampling interval. +const size_t kMonitorTraceEventBufferSize = 30000; const int kThreadFlushTimeoutMs = 1000; @@ -97,6 +99,7 @@ LazyInstance<ThreadLocalPointer<const char> >::Leaky const char kRecordUntilFull[] = "record-until-full"; const char kRecordContinuously[] = "record-continuously"; const char kEnableSampling[] = "enable-sampling"; +const char kMonitorSampling[] = "monitor-sampling"; TimeTicks ThreadNow() { return TimeTicks::IsThreadNowSupported() ? @@ -105,10 +108,11 @@ TimeTicks ThreadNow() { class TraceBufferRingBuffer : public TraceBuffer { public: - TraceBufferRingBuffer() + TraceBufferRingBuffer(size_t buffer_size) : unused_event_index_(0), - oldest_event_index_(0) { - logged_events_.reserve(kTraceEventInitialBufferSize); + oldest_event_index_(0), + buffer_size_(buffer_size) { + logged_events_.reserve(buffer_size_); } virtual ~TraceBufferRingBuffer() {} @@ -119,9 +123,10 @@ class TraceBufferRingBuffer : public TraceBuffer { else logged_events_.push_back(event); - unused_event_index_ = NextIndex(unused_event_index_); + unused_event_index_ = NextIndex(unused_event_index_, buffer_size_); if (unused_event_index_ == oldest_event_index_) { - oldest_event_index_ = NextIndex(oldest_event_index_); + oldest_event_index_ = NextIndex( + oldest_event_index_, buffer_size_); } } @@ -133,7 +138,7 @@ class TraceBufferRingBuffer : public TraceBuffer { DCHECK(HasMoreEvents()); size_t next = oldest_event_index_; - oldest_event_index_ = NextIndex(oldest_event_index_); + oldest_event_index_ = NextIndex(oldest_event_index_, buffer_size_); return GetEventAt(next); } @@ -152,7 +157,7 @@ class TraceBufferRingBuffer : public TraceBuffer { strcmp(event_name.c_str(), event.name()) == 0) { ++notify_count; } - index = NextIndex(index); + index = NextIndex(index, buffer_size_); } return notify_count; } @@ -170,16 +175,29 @@ class TraceBufferRingBuffer : public TraceBuffer { return kTraceEventRingBufferSize; } + virtual TraceBuffer* Clone() const OVERRIDE { + TraceBufferRingBuffer* clonedBuffer = + new TraceBufferRingBuffer(buffer_size_); + size_t index = oldest_event_index_; + while (index != unused_event_index_) { + const TraceEvent& event = GetEventAt(index); + clonedBuffer->AddEvent(event); + index = NextIndex(index, buffer_size_); + } + return clonedBuffer; + } + private: - static size_t NextIndex(size_t index) { + static size_t NextIndex(size_t index, size_t buffer_size) { index++; - if (index >= kTraceEventRingBufferSize) + if (index >= buffer_size) index = 0; return index; } size_t unused_event_index_; size_t oldest_event_index_; + size_t buffer_size_; std::vector<TraceEvent> logged_events_; DISALLOW_COPY_AND_ASSIGN(TraceBufferRingBuffer); @@ -246,6 +264,11 @@ class TraceBufferVector : public TraceBuffer { return kTraceEventVectorBufferSize; } + virtual TraceBuffer* Clone() const OVERRIDE { + NOTIMPLEMENTED(); + return NULL; + } + private: size_t current_iteration_index_; std::vector<TraceEvent> logged_events_; @@ -282,6 +305,11 @@ class TraceBufferDiscardsEvents : public TraceBuffer { NOTREACHED(); return *static_cast<TraceEvent*>(NULL); } + + virtual TraceBuffer* Clone() const OVERRIDE { + NOTIMPLEMENTED(); + return NULL; + } }; } // namespace @@ -669,7 +697,7 @@ class TraceSamplingThread : public PlatformThread::Delegate { // Implementation of PlatformThread::Delegate: virtual void ThreadMain() OVERRIDE; - static void DefaultSampleCallback(TraceBucketData* bucekt_data); + static void DefaultSamplingCallback(TraceBucketData* bucekt_data); void Stop(); void InstallWaitableEventForSamplingTesting(WaitableEvent* waitable_event); @@ -716,7 +744,8 @@ void TraceSamplingThread::ThreadMain() { } // static -void TraceSamplingThread::DefaultSampleCallback(TraceBucketData* bucket_data) { +void TraceSamplingThread::DefaultSamplingCallback( + TraceBucketData* bucket_data) { TRACE_EVENT_API_ATOMIC_WORD category_and_name = TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket); if (!category_and_name) @@ -763,7 +792,6 @@ void TraceSamplingThread::InstallWaitableEventForSamplingTesting( waitable_event_for_testing_.reset(waitable_event); } - TraceBucketData::TraceBucketData(base::subtle::AtomicWord* bucket, const char* name, TraceSampleCallback callback) @@ -957,6 +985,8 @@ TraceLog::Options TraceLog::TraceOptionsFromString(const std::string& options) { ret |= RECORD_CONTINUOUSLY; } else if (*iter == kEnableSampling) { ret |= ENABLE_SAMPLING; + } else if (*iter == kMonitorSampling) { + ret |= MONITOR_SAMPLING; } else { NOTREACHED(); // Unknown option provided. } @@ -1160,20 +1190,20 @@ void TraceLog::SetEnabled(const CategoryFilter& category_filter, category_filter_ = CategoryFilter(category_filter); UpdateCategoryGroupEnabledFlags(); - if (options & ENABLE_SAMPLING) { + if ((options & ENABLE_SAMPLING) || (options & MONITOR_SAMPLING)) { sampling_thread_.reset(new TraceSamplingThread); sampling_thread_->RegisterSampleBucket( &g_trace_state[0], "bucket0", - Bind(&TraceSamplingThread::DefaultSampleCallback)); + Bind(&TraceSamplingThread::DefaultSamplingCallback)); sampling_thread_->RegisterSampleBucket( &g_trace_state[1], "bucket1", - Bind(&TraceSamplingThread::DefaultSampleCallback)); + Bind(&TraceSamplingThread::DefaultSamplingCallback)); sampling_thread_->RegisterSampleBucket( &g_trace_state[2], "bucket2", - Bind(&TraceSamplingThread::DefaultSampleCallback)); + Bind(&TraceSamplingThread::DefaultSamplingCallback)); if (!PlatformThread::Create( 0, sampling_thread_.get(), &sampling_thread_handle_)) { DCHECK(false) << "failed to create thread"; @@ -1287,7 +1317,9 @@ void TraceLog::SetNotificationCallback( TraceBuffer* TraceLog::GetTraceBuffer() { Options options = trace_options(); if (options & RECORD_CONTINUOUSLY) - return new TraceBufferRingBuffer(); + return new TraceBufferRingBuffer(kTraceEventRingBufferSize); + else if (options & MONITOR_SAMPLING) + return new TraceBufferRingBuffer(kMonitorTraceEventBufferSize); else if (options & ECHO_TO_CONSOLE) return new TraceBufferDiscardsEvents(); return new TraceBufferVector(); @@ -1366,27 +1398,13 @@ void TraceLog::Flush(const TraceLog::OutputCallback& cb) { FinishFlush(flush_count); } -void TraceLog::FinishFlush(int flush_count) { - scoped_ptr<TraceBuffer> previous_logged_events; - OutputCallback flush_output_callback; - - { - AutoLock lock(lock_); - if (flush_count != flush_count_) - return; - - previous_logged_events.swap(logged_events_); - logged_events_.reset(GetTraceBuffer()); - subtle::NoBarrier_Store(&buffer_is_full_, 0); - flush_message_loop_proxy_ = NULL; - flush_output_callback = flush_output_callback_; - flush_output_callback_.Reset(); - } - +void TraceLog::ConvertTraceEventsToTraceFormat( + scoped_ptr<TraceBuffer> logged_events, + const TraceLog::OutputCallback& flush_output_callback) { if (flush_output_callback.is_null()) return; - bool has_more_events = previous_logged_events->HasMoreEvents(); + bool has_more_events = logged_events->HasMoreEvents(); // The callback need to be called at least once even if there is no events // to let the caller know the completion of flush. do { @@ -1397,16 +1415,37 @@ void TraceLog::FinishFlush(int flush_count) { if (i > 0) *(&(json_events_str_ptr->data())) += ","; - previous_logged_events->NextEvent().AppendAsJSON( + logged_events->NextEvent().AppendAsJSON( &(json_events_str_ptr->data())); - has_more_events = previous_logged_events->HasMoreEvents(); + has_more_events = logged_events->HasMoreEvents(); } flush_output_callback.Run(json_events_str_ptr, has_more_events); } while (has_more_events); } +void TraceLog::FinishFlush(int flush_count) { + scoped_ptr<TraceBuffer> previous_logged_events; + OutputCallback flush_output_callback; + + { + AutoLock lock(lock_); + if (flush_count != flush_count_) + return; + + previous_logged_events.swap(logged_events_); + logged_events_.reset(GetTraceBuffer()); + subtle::NoBarrier_Store(&buffer_is_full_, 0); + flush_message_loop_proxy_ = NULL; + flush_output_callback = flush_output_callback_; + flush_output_callback_.Reset(); + } + + ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(), + flush_output_callback); +} + // Run in each thread holding a local event buffer. void TraceLog::FlushCurrentThread(int flush_count) { { @@ -1445,6 +1484,22 @@ void TraceLog::OnFlushTimeout(int flush_count) { FinishFlush(flush_count); } +void TraceLog::FlushButLeaveBufferIntact( + const TraceLog::OutputCallback& flush_output_callback) { + if (!sampling_thread_) + return; + + scoped_ptr<TraceBuffer> previous_logged_events; + { + AutoLock lock(lock_); + AddMetadataEvents(); + previous_logged_events.reset(logged_events_->Clone()); + } // release lock + + ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(), + flush_output_callback); +} + void TraceLog::AddTraceEvent( char phase, const unsigned char* category_group_enabled, @@ -1743,6 +1798,7 @@ void TraceLog::AddMetadataEvents() { it++) { if (it->second.empty()) continue; + AddMetadataEventToBuffer(logged_events_.get(), it->first, "thread_name", "name", @@ -1752,6 +1808,8 @@ void TraceLog::AddMetadataEvents() { void TraceLog::InstallWaitableEventForSamplingTesting( WaitableEvent* waitable_event) { + if (!sampling_thread_) + return; sampling_thread_->InstallWaitableEventForSamplingTesting(waitable_event); } @@ -1791,7 +1849,7 @@ void TraceLog::UpdateProcessLabel( void TraceLog::RemoveProcessLabel(int label_id) { AutoLock lock(lock_); base::hash_map<int, std::string>::iterator it = process_labels_.find( - label_id); + label_id); if (it == process_labels_.end()) return; @@ -1987,7 +2045,7 @@ ScopedTrace::ScopedTrace( name_ = name; TRACE_EVENT_API_ADD_TRACE_EVENT( TRACE_EVENT_PHASE_BEGIN, // phase - category_group_enabled_, // category enabled + category_group_enabled_, // category enabled name, // name 0, // id 0, // num_args |