Commit e507d09a authored by Eric Seckler's avatar Eric Seckler Committed by Commit Bot

perfetto: Switch to clearing incremental state periodically

The perfetto service now provides a signal for clearing of incremental
state. This patch plumbs the signal into our data sources down to the
event sink.

Bug: 928738
Change-Id: If4bfb5329eb50e8222cd670ed4a0ece0ad25081e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1632213Reviewed-by: default avataroysteine <oysteine@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Eric Seckler <eseckler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664154}
parent 19ae65d1
...@@ -132,7 +132,10 @@ void ProducerHost::Flush( ...@@ -132,7 +132,10 @@ void ProducerHost::Flush(
} }
void ProducerHost::ClearIncrementalState(const perfetto::DataSourceInstanceID*, void ProducerHost::ClearIncrementalState(const perfetto::DataSourceInstanceID*,
size_t) {} size_t) {
DCHECK(producer_client_);
producer_client_->ClearIncrementalState();
}
// This data can come from a malicious child process. We don't do any // This data can come from a malicious child process. We don't do any
// sanitization here because ProducerEndpoint::CommitData() (And any other // sanitization here because ProducerEndpoint::CommitData() (And any other
......
...@@ -51,6 +51,10 @@ perfetto::TraceConfig GetDefaultPerfettoConfig( ...@@ -51,6 +51,10 @@ perfetto::TraceConfig GetDefaultPerfettoConfig(
builtin_data_sources->set_disable_trace_config(privacy_filtering_enabled); builtin_data_sources->set_disable_trace_config(privacy_filtering_enabled);
builtin_data_sources->set_disable_system_info(privacy_filtering_enabled); builtin_data_sources->set_disable_system_info(privacy_filtering_enabled);
// Clear incremental state every 5 seconds, so that we lose at most the first
// 5 seconds of the trace (if we wrap around perfetto's central buffer).
perfetto_config.mutable_incremental_state_config()->set_clear_period_ms(5000);
// We strip the process filter from the config string we send to Perfetto, // We strip the process filter from the config string we send to Perfetto,
// so perfetto doesn't reject it from a future // so perfetto doesn't reject it from a future
// TracingService::ChangeTraceConfig call due to being an unsupported // TracingService::ChangeTraceConfig call due to being an unsupported
......
...@@ -48,6 +48,8 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final { ...@@ -48,6 +48,8 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
// Flush the data source. // Flush the data source.
virtual void Flush(base::RepeatingClosure flush_complete_callback) = 0; virtual void Flush(base::RepeatingClosure flush_complete_callback) = 0;
virtual void ClearIncrementalState() {}
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
uint64_t data_source_id() const { return data_source_id_; } uint64_t data_source_id() const { return data_source_id_; }
......
...@@ -92,6 +92,7 @@ void ProducerClient::NewDataSourceAdded( ...@@ -92,6 +92,7 @@ void ProducerClient::NewDataSourceAdded(
new_registration.set_name(data_source->name()); new_registration.set_name(data_source->name());
new_registration.set_will_notify_on_start(true); new_registration.set_will_notify_on_start(true);
new_registration.set_will_notify_on_stop(true); new_registration.set_will_notify_on_stop(true);
new_registration.set_handles_incremental_state_clear(true);
producer_host_->RegisterDataSource(std::move(new_registration)); producer_host_->RegisterDataSource(std::move(new_registration));
} }
...@@ -175,6 +176,12 @@ void ProducerClient::Flush(uint64_t flush_request_id, ...@@ -175,6 +176,12 @@ void ProducerClient::Flush(uint64_t flush_request_id,
} }
} }
void ProducerClient::ClearIncrementalState() {
for (auto* data_source : PerfettoTracedProcess::Get()->data_sources()) {
data_source->ClearIncrementalState();
}
}
void ProducerClient::RegisterDataSource(const perfetto::DataSourceDescriptor&) { void ProducerClient::RegisterDataSource(const perfetto::DataSourceDescriptor&) {
NOTREACHED(); NOTREACHED();
} }
......
...@@ -61,6 +61,7 @@ class COMPONENT_EXPORT(TRACING_CPP) ProducerClient ...@@ -61,6 +61,7 @@ class COMPONENT_EXPORT(TRACING_CPP) ProducerClient
void StopDataSource(uint64_t id, StopDataSourceCallback callback) override; void StopDataSource(uint64_t id, StopDataSourceCallback callback) override;
void Flush(uint64_t flush_request_id, void Flush(uint64_t flush_request_id,
const std::vector<uint64_t>& data_source_ids) override; const std::vector<uint64_t>& data_source_ids) override;
void ClearIncrementalState() override;
// perfetto::TracingService::ProducerEndpoint implementation. // perfetto::TracingService::ProducerEndpoint implementation.
// Used by the TraceWriters // Used by the TraceWriters
......
...@@ -25,6 +25,4 @@ ThreadLocalEventSink::~ThreadLocalEventSink() { ...@@ -25,6 +25,4 @@ ThreadLocalEventSink::~ThreadLocalEventSink() {
std::move(trace_writer_)); std::move(trace_writer_));
} }
void ThreadLocalEventSink::ResetIncrementalState() {}
} // namespace tracing } // namespace tracing
...@@ -44,8 +44,6 @@ class COMPONENT_EXPORT(TRACING_CPP) ThreadLocalEventSink { ...@@ -44,8 +44,6 @@ class COMPONENT_EXPORT(TRACING_CPP) ThreadLocalEventSink {
virtual void Flush() = 0; virtual void Flush() = 0;
virtual void ResetIncrementalState();
uint32_t session_id() const { return session_id_; } uint32_t session_id() const { return session_id_; }
protected: protected:
......
...@@ -368,12 +368,8 @@ void TraceEventDataSource::Flush( ...@@ -368,12 +368,8 @@ void TraceEventDataSource::Flush(
std::move(flush_complete_callback))); std::move(flush_complete_callback)));
} }
void TraceEventDataSource::ResetIncrementalStateForTesting() { void TraceEventDataSource::ClearIncrementalState() {
auto* thread_local_event_sink = TrackEventThreadLocalEventSink::ClearIncrementalState();
static_cast<ThreadLocalEventSink*>(ThreadLocalEventSinkSlot()->Get());
if (thread_local_event_sink) {
thread_local_event_sink->ResetIncrementalState();
}
} }
ThreadLocalEventSink* TraceEventDataSource::CreateThreadLocalEventSink( ThreadLocalEventSink* TraceEventDataSource::CreateThreadLocalEventSink(
......
...@@ -112,11 +112,7 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource ...@@ -112,11 +112,7 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource
// Called from the PerfettoProducer. // Called from the PerfettoProducer.
void StopTracing(base::OnceClosure stop_complete_callback) override; void StopTracing(base::OnceClosure stop_complete_callback) override;
void Flush(base::RepeatingClosure flush_complete_callback) override; void Flush(base::RepeatingClosure flush_complete_callback) override;
void ClearIncrementalState() override;
// Resets emitted incremental state on the current thread and causes
// incremental data (e.g. interning index entries and a ThreadDescriptor) to
// be emitted again.
void ResetIncrementalStateForTesting();
// Deletes TraceWriter safely on behalf of a ThreadLocalEventSink. // Deletes TraceWriter safely on behalf of a ThreadLocalEventSink.
void ReturnTraceWriter( void ReturnTraceWriter(
......
...@@ -915,7 +915,7 @@ TEST_F(TraceEventDataSourceTest, InternedStrings) { ...@@ -915,7 +915,7 @@ TEST_F(TraceEventDataSourceTest, InternedStrings) {
// Resetting the interning state causes ThreadDescriptor and interning // Resetting the interning state causes ThreadDescriptor and interning
// entries to be emitted again, with the same interning IDs. // entries to be emitted again, with the same interning IDs.
TraceEventDataSource::GetInstance()->ResetIncrementalStateForTesting(); TraceEventDataSource::GetInstance()->ClearIncrementalState();
} }
} }
......
...@@ -34,12 +34,6 @@ namespace { ...@@ -34,12 +34,6 @@ namespace {
constexpr uint32_t kMagicChunkIndex = constexpr uint32_t kMagicChunkIndex =
base::trace_event::TraceBufferChunk::kMaxChunkIndex; base::trace_event::TraceBufferChunk::kMaxChunkIndex;
// Force an incremental state reset every 1000 events on each thread. This
// limits the maximum number of events we lose when trace buffers wrap.
// TODO(eseckler): Tune this value experimentally and/or replace it with a
// signal by the service.
constexpr int kMaxEventsBeforeIncrementalStateReset = 1000;
// Replacement string for names of events with TRACE_EVENT_FLAG_COPY. // Replacement string for names of events with TRACE_EVENT_FLAG_COPY.
const char* const kPrivacyFiltered = "PRIVACY_FILTERED"; const char* const kPrivacyFiltered = "PRIVACY_FILTERED";
...@@ -119,6 +113,10 @@ void WriteDebugAnnotations( ...@@ -119,6 +113,10 @@ void WriteDebugAnnotations(
// static // static
constexpr size_t TrackEventThreadLocalEventSink::kMaxCompleteEventDepth; constexpr size_t TrackEventThreadLocalEventSink::kMaxCompleteEventDepth;
// static
std::atomic<uint32_t>
TrackEventThreadLocalEventSink::incremental_state_reset_id_{0};
TrackEventThreadLocalEventSink::TrackEventThreadLocalEventSink( TrackEventThreadLocalEventSink::TrackEventThreadLocalEventSink(
std::unique_ptr<perfetto::StartupTraceWriter> trace_writer, std::unique_ptr<perfetto::StartupTraceWriter> trace_writer,
uint32_t session_id, uint32_t session_id,
...@@ -138,11 +136,9 @@ TrackEventThreadLocalEventSink::TrackEventThreadLocalEventSink( ...@@ -138,11 +136,9 @@ TrackEventThreadLocalEventSink::TrackEventThreadLocalEventSink(
TrackEventThreadLocalEventSink::~TrackEventThreadLocalEventSink() {} TrackEventThreadLocalEventSink::~TrackEventThreadLocalEventSink() {}
// TODO(eseckler): Trigger this upon a signal from the perfetto, once perfetto // static
// supports this. void TrackEventThreadLocalEventSink::ClearIncrementalState() {
void TrackEventThreadLocalEventSink::ResetIncrementalState() { incremental_state_reset_id_.fetch_add(1u, std::memory_order_relaxed);
reset_incremental_state_ = true;
events_since_last_incremental_state_reset_ = 0;
} }
void TrackEventThreadLocalEventSink::AddTraceEvent( void TrackEventThreadLocalEventSink::AddTraceEvent(
...@@ -176,6 +172,15 @@ void TrackEventThreadLocalEventSink::AddTraceEvent( ...@@ -176,6 +172,15 @@ void TrackEventThreadLocalEventSink::AddTraceEvent(
bool copy_strings = flags & TRACE_EVENT_FLAG_COPY; bool copy_strings = flags & TRACE_EVENT_FLAG_COPY;
bool explicit_timestamp = flags & TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP; bool explicit_timestamp = flags & TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP;
// We access |incremental_state_reset_id_| atomically but racily. It's OK if
// we don't notice the reset request immediately, as long as we will notice
// and service it eventually.
auto reset_id = incremental_state_reset_id_.load(std::memory_order_relaxed);
if (reset_id != last_incremental_state_reset_id_) {
reset_incremental_state_ = true;
last_incremental_state_reset_id_ = reset_id;
}
if (reset_incremental_state_) { if (reset_incremental_state_) {
interned_event_categories_.ResetEmittedState(); interned_event_categories_.ResetEmittedState();
interned_event_names_.ResetEmittedState(); interned_event_names_.ResetEmittedState();
...@@ -456,12 +461,6 @@ void TrackEventThreadLocalEventSink::AddTraceEvent( ...@@ -456,12 +461,6 @@ void TrackEventThreadLocalEventSink::AddTraceEvent(
interned_annotation_names_.Clear(); interned_annotation_names_.Clear();
interned_source_locations_.Clear(); interned_source_locations_.Clear();
} }
events_since_last_incremental_state_reset_++;
if (events_since_last_incremental_state_reset_ >=
kMaxEventsBeforeIncrementalStateReset) {
ResetIncrementalState();
}
} }
void TrackEventThreadLocalEventSink::UpdateDuration( void TrackEventThreadLocalEventSink::UpdateDuration(
......
...@@ -34,8 +34,11 @@ class COMPONENT_EXPORT(TRACING_CPP) TrackEventThreadLocalEventSink ...@@ -34,8 +34,11 @@ class COMPONENT_EXPORT(TRACING_CPP) TrackEventThreadLocalEventSink
bool proto_writer_filtering_enabled); bool proto_writer_filtering_enabled);
~TrackEventThreadLocalEventSink() override; ~TrackEventThreadLocalEventSink() override;
// Resets emitted incremental state on all threads and causes incremental data
// (e.g. interning index entries and a ThreadDescriptor) to be emitted again.
static void ClearIncrementalState();
// ThreadLocalEventSink implementation: // ThreadLocalEventSink implementation:
void ResetIncrementalState() override;
void AddTraceEvent(base::trace_event::TraceEvent* trace_event, void AddTraceEvent(base::trace_event::TraceEvent* trace_event,
base::trace_event::TraceEventHandle* handle) override; base::trace_event::TraceEventHandle* handle) override;
void UpdateDuration(base::trace_event::TraceEventHandle handle, void UpdateDuration(base::trace_event::TraceEventHandle handle,
...@@ -54,12 +57,14 @@ class COMPONENT_EXPORT(TRACING_CPP) TrackEventThreadLocalEventSink ...@@ -54,12 +57,14 @@ class COMPONENT_EXPORT(TRACING_CPP) TrackEventThreadLocalEventSink
InterningIndex<std::pair<const char*, const char*>> InterningIndex<std::pair<const char*, const char*>>
interned_source_locations_; interned_source_locations_;
static std::atomic<uint32_t> incremental_state_reset_id_;
bool reset_incremental_state_ = true; bool reset_incremental_state_ = true;
uint32_t last_incremental_state_reset_id_ = 0;
base::TimeTicks last_timestamp_; base::TimeTicks last_timestamp_;
base::ThreadTicks last_thread_time_; base::ThreadTicks last_thread_time_;
int process_id_; int process_id_;
int thread_id_; int thread_id_;
int events_since_last_incremental_state_reset_ = 0;
base::trace_event::TraceEvent complete_event_stack_[kMaxCompleteEventDepth]; base::trace_event::TraceEvent complete_event_stack_[kMaxCompleteEventDepth];
uint32_t current_stack_depth_ = 0; uint32_t current_stack_depth_ = 0;
......
...@@ -18,6 +18,8 @@ bool StructTraits<tracing::mojom::DataSourceRegistrationDataView, ...@@ -18,6 +18,8 @@ bool StructTraits<tracing::mojom::DataSourceRegistrationDataView,
out->set_name(name); out->set_name(name);
out->set_will_notify_on_start(data.will_notify_on_start()); out->set_will_notify_on_start(data.will_notify_on_start());
out->set_will_notify_on_stop(data.will_notify_on_stop()); out->set_will_notify_on_stop(data.will_notify_on_stop());
out->set_handles_incremental_state_clear(
data.handles_incremental_state_clear());
return true; return true;
} }
} // namespace mojo } // namespace mojo
...@@ -28,6 +28,10 @@ class StructTraits<tracing::mojom::DataSourceRegistrationDataView, ...@@ -28,6 +28,10 @@ class StructTraits<tracing::mojom::DataSourceRegistrationDataView,
static bool will_notify_on_stop(const perfetto::DataSourceDescriptor& src) { static bool will_notify_on_stop(const perfetto::DataSourceDescriptor& src) {
return src.will_notify_on_stop(); return src.will_notify_on_stop();
} }
static bool handles_incremental_state_clear(
const perfetto::DataSourceDescriptor& src) {
return src.handles_incremental_state_clear();
}
static bool Read(tracing::mojom::DataSourceRegistrationDataView data, static bool Read(tracing::mojom::DataSourceRegistrationDataView data,
perfetto::DataSourceDescriptor* out); perfetto::DataSourceDescriptor* out);
......
...@@ -90,6 +90,7 @@ struct DataSourceRegistration { ...@@ -90,6 +90,7 @@ struct DataSourceRegistration {
string name; string name;
bool will_notify_on_start; bool will_notify_on_start;
bool will_notify_on_stop; bool will_notify_on_stop;
bool handles_incremental_state_clear;
}; };
// This is implemented by the tracing service and represents the service- // This is implemented by the tracing service and represents the service-
...@@ -127,6 +128,7 @@ interface ProducerClient { ...@@ -127,6 +128,7 @@ interface ProducerClient {
// sent in the StartDataSource call. // sent in the StartDataSource call.
StopDataSource(uint64 id) => (); StopDataSource(uint64 id) => ();
Flush(uint64 flush_request_id, array<uint64> data_source_ids); Flush(uint64 flush_request_id, array<uint64> data_source_ids);
ClearIncrementalState();
}; };
// This is implemented by the tracing service, and is essentially a singleton // This is implemented by the tracing service, and is essentially a singleton
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment