diff options
author | Yabin Cui <yabinc@google.com> | 2024-05-08 21:28:54 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2024-05-08 21:28:54 +0000 |
commit | 88815e57fb998bbdc92bc3acad91a12d6755c904 (patch) | |
tree | d9f08a11df1cb0fe825a4777a1cb38c7cf878f4a | |
parent | 10ea6cc8b454565df086dad5f05c7ff29661880a (diff) | |
parent | 7a59f85e59772f2de6315195bffc3290ec730b83 (diff) | |
download | extras-88815e57fb998bbdc92bc3acad91a12d6755c904.tar.gz |
Merge changes Ib892aeea,I1b5f2b85,I449517fb,I6583aebc into main
* changes:
simpleperf: Delay processing ETM data until the buffer is half full
simpleperf: Rotate the last cpu disabling ETM events
simpleperf: Flush ETM data at the end of recording
simpleperf: Enable ETM events after create aux buffer
-rw-r--r-- | simpleperf/RecordReadThread.cpp | 12 | ||||
-rw-r--r-- | simpleperf/RecordReadThread.h | 1 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 17 | ||||
-rw-r--r-- | simpleperf/event_selection_set.cpp | 70 | ||||
-rw-r--r-- | simpleperf/event_selection_set.h | 6 |
5 files changed, 103 insertions, 3 deletions
diff --git a/simpleperf/RecordReadThread.cpp b/simpleperf/RecordReadThread.cpp index 2ab61278..2d034bc1 100644 --- a/simpleperf/RecordReadThread.cpp +++ b/simpleperf/RecordReadThread.cpp @@ -408,6 +408,7 @@ bool RecordReadThread::HandleAddEventFds(IOEventLoop& loop, success = false; break; } + has_etm_events_ = true; } cpu_map[fd->Cpu()] = fd; } else { @@ -620,6 +621,9 @@ void RecordReadThread::PushRecordToRecordBuffer(KernelRecordReader* kernel_recor } void RecordReadThread::ReadAuxDataFromKernelBuffer(bool* has_data) { + if (!has_etm_events_) { + return; + } for (auto& reader : kernel_record_readers_) { EventFd* event_fd = reader.GetEventFd(); if (event_fd->HasAuxBuffer()) { @@ -659,6 +663,14 @@ void RecordReadThread::ReadAuxDataFromKernelBuffer(bool* has_data) { } bool RecordReadThread::SendDataNotificationToMainThread() { + if (has_etm_events_) { + // For ETM recording, the default buffer size is large enough to hold ETM data for several + // seconds. To reduce impact of processing ETM data (especially when --decode-etm is used), + // delay processing ETM data until the buffer is half full. + if (record_buffer_.GetFreeSize() >= record_buffer_.size() / 2) { + return true; + } + } if (!has_data_notification_.load(std::memory_order_relaxed)) { has_data_notification_ = true; char unused = 0; diff --git a/simpleperf/RecordReadThread.h b/simpleperf/RecordReadThread.h index c104b083..893f8234 100644 --- a/simpleperf/RecordReadThread.h +++ b/simpleperf/RecordReadThread.h @@ -211,6 +211,7 @@ class RecordReadThread { std::unique_ptr<std::thread> read_thread_; std::vector<KernelRecordReader> kernel_record_readers_; pid_t exclude_pid_ = -1; + bool has_etm_events_ = false; std::unordered_set<EventFd*> event_fds_disabled_by_kernel_; diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 40582045..d57c3422 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -631,7 +631,7 @@ bool RecordCommand::PrepareRecording(Workload* workload) { } else { need_to_check_targets = true; } - if (delay_in_ms_ != 0) { + if (delay_in_ms_ != 0 || event_selection_set_.HasAuxTrace()) { event_selection_set_.SetEnableCondition(false, false); } @@ -755,6 +755,12 @@ bool RecordCommand::PrepareRecording(Workload* workload) { } } if (event_selection_set_.HasAuxTrace()) { + // ETM events can only be enabled successfully after MmapEventFiles(). + if (delay_in_ms_ == 0 && !event_selection_set_.IsEnabledOnExec()) { + if (!event_selection_set_.EnableETMEvents()) { + return false; + } + } // ETM data is dumped to kernel buffer only when there is no thread traced by ETM. It happens // either when all monitored threads are scheduled off cpu, or when all etm perf events are // disabled. @@ -762,8 +768,7 @@ bool RecordCommand::PrepareRecording(Workload* workload) { // makes less than expected data, especially in system wide recording. So add a periodic event // to flush etm data by temporarily disable all perf events. auto etm_flush = [this]() { - return event_selection_set_.SetEnableEvents(false) && - event_selection_set_.SetEnableEvents(true); + return event_selection_set_.DisableETMEvents() && event_selection_set_.EnableETMEvents(); }; if (!loop->AddPeriodicEvent(SecondToTimeval(kDefaultEtmDataFlushPeriodInSec), etm_flush)) { return false; @@ -800,6 +805,12 @@ bool RecordCommand::DoRecording(Workload* workload) { return false; } time_stat_.stop_recording_time = GetSystemClock(); + if (event_selection_set_.HasAuxTrace()) { + // Disable ETM events to flush the last ETM data. + if (!event_selection_set_.DisableETMEvents()) { + return false; + } + } if (!event_selection_set_.SyncKernelBuffer()) { return false; } diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp index c75f8049..1a7cdef8 100644 --- a/simpleperf/event_selection_set.cpp +++ b/simpleperf/event_selection_set.cpp @@ -233,6 +233,8 @@ bool EventSelectionSet::BuildAndCheckEventSelection(const std::string& event_nam // enabling/disabling etm devices. So don't adjust frequency by default. selection->event_attr.freq = 0; selection->event_attr.sample_period = 1; + // An ETM event can't be enabled without mmap aux buffer. So disable it by default. + selection->event_attr.disabled = 1; } else { selection->event_attr.freq = 1; // Set default sample freq here may print msg "Adjust sample freq to max allowed sample @@ -461,6 +463,17 @@ void EventSelectionSet::SetEnableCondition(bool enable_on_open, bool enable_on_e } } +bool EventSelectionSet::IsEnabledOnExec() const { + for (const auto& group : groups_) { + for (const auto& selection : group.selections) { + if (!selection.event_attr.enable_on_exec) { + return false; + } + } + } + return true; +} + void EventSelectionSet::SampleIdAll() { for (auto& group : groups_) { for (auto& selection : group.selections) { @@ -939,4 +952,61 @@ bool EventSelectionSet::SetEnableEvents(bool enable) { return true; } +bool EventSelectionSet::EnableETMEvents() { + for (auto& group : groups_) { + for (auto& sel : group.selections) { + if (!sel.event_type_modifier.event_type.IsEtmEvent()) { + continue; + } + for (auto& fd : sel.event_fds) { + if (!fd->SetEnableEvent(true)) { + return false; + } + } + } + } + return true; +} + +bool EventSelectionSet::DisableETMEvents() { + for (auto& group : groups_) { + for (auto& sel : group.selections) { + if (!sel.event_type_modifier.event_type.IsEtmEvent()) { + continue; + } + // When using ETR, ETM data is flushed to the aux buffer of the last cpu disabling ETM events. + // To avoid overflowing the aux buffer for one cpu, rotate the last cpu disabling ETM events. + if (etm_event_cpus_.empty()) { + for (const auto& fd : sel.event_fds) { + etm_event_cpus_.insert(fd->Cpu()); + } + if (etm_event_cpus_.empty()) { + continue; + } + etm_event_cpus_it_ = etm_event_cpus_.begin(); + } + int last_disabled_cpu = *etm_event_cpus_it_; + if (++etm_event_cpus_it_ == etm_event_cpus_.end()) { + etm_event_cpus_it_ = etm_event_cpus_.begin(); + } + + for (auto& fd : sel.event_fds) { + if (fd->Cpu() != last_disabled_cpu) { + if (!fd->SetEnableEvent(false)) { + return false; + } + } + } + for (auto& fd : sel.event_fds) { + if (fd->Cpu() == last_disabled_cpu) { + if (!fd->SetEnableEvent(false)) { + return false; + } + } + } + } + } + return true; +} + } // namespace simpleperf diff --git a/simpleperf/event_selection_set.h b/simpleperf/event_selection_set.h index e046035b..a892d51e 100644 --- a/simpleperf/event_selection_set.h +++ b/simpleperf/event_selection_set.h @@ -122,6 +122,7 @@ class EventSelectionSet { std::map<int, size_t> GetHardwareCountersForCpus() const; void SetEnableCondition(bool enable_on_open, bool enable_on_exec); + bool IsEnabledOnExec() const; void SampleIdAll(); // Only set sample rate for events that haven't set sample rate. void SetSampleRateForNewEvents(const SampleRate& rate); @@ -179,6 +180,8 @@ class EventSelectionSet { double check_interval_in_sec = DEFAULT_PERIOD_TO_CHECK_MONITORED_TARGETS_IN_SEC); bool SetEnableEvents(bool enable); + bool EnableETMEvents(); + bool DisableETMEvents(); private: struct EventSelection { @@ -232,6 +235,9 @@ class EventSelectionSet { std::optional<SampleRate> sample_rate_; std::optional<std::vector<int>> cpus_; + std::set<int> etm_event_cpus_; + std::set<int>::const_iterator etm_event_cpus_it_; + DISALLOW_COPY_AND_ASSIGN(EventSelectionSet); }; |