summaryrefslogtreecommitdiffstats
path: root/base/debug/trace_event_impl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/debug/trace_event_impl.cc')
-rw-r--r--base/debug/trace_event_impl.cc136
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