diff options
author | Yabin Cui <yabinc@google.com> | 2022-04-01 17:33:18 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2022-04-01 17:33:18 +0000 |
commit | 09fe7d7b481147f5a4220555a33a615de4093fb7 (patch) | |
tree | c1d7043425408173045ba87986230513ec861527 | |
parent | e518a5d38e7587bf2f626e93b2d288bf150c2eb6 (diff) | |
parent | c3cc93bbe0030a4ff53f17e07629a193cebad959 (diff) | |
download | extras-09fe7d7b481147f5a4220555a33a615de4093fb7.tar.gz |
Merge changes Ib0160fe1,Ib5a11b7c
* changes:
simpleperf: raise priority of stop recording events.
simpleperf: Make stop recording time more accurate.
-rw-r--r-- | simpleperf/IOEventLoop.cpp | 32 | ||||
-rw-r--r-- | simpleperf/IOEventLoop.h | 24 | ||||
-rw-r--r-- | simpleperf/IOEventLoop_test.cpp | 42 | ||||
-rw-r--r-- | simpleperf/cmd_monitor.cpp | 13 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 29 | ||||
-rw-r--r-- | simpleperf/event_selection_set.cpp | 9 |
6 files changed, 109 insertions, 40 deletions
diff --git a/simpleperf/IOEventLoop.cpp b/simpleperf/IOEventLoop.cpp index 06bdd713..239fff97 100644 --- a/simpleperf/IOEventLoop.cpp +++ b/simpleperf/IOEventLoop.cpp @@ -84,6 +84,10 @@ bool IOEventLoop::EnsureInit() { return false; } event_config_free(cfg); + if (event_base_priority_init(ebase_, 2) != 0) { + LOG(ERROR) << "event_base_priority_init failed"; + return false; + } } if (ebase_ == nullptr) { LOG(ERROR) << "failed to create event_base"; @@ -110,39 +114,44 @@ static bool MakeFdNonBlocking(int fd) { return true; } -IOEventRef IOEventLoop::AddReadEvent(int fd, const std::function<bool()>& callback) { +IOEventRef IOEventLoop::AddReadEvent(int fd, const std::function<bool()>& callback, + IOEventPriority priority) { if (!MakeFdNonBlocking(fd)) { return nullptr; } - return AddEvent(fd, EV_READ | EV_PERSIST, nullptr, callback); + return AddEvent(fd, EV_READ | EV_PERSIST, nullptr, callback, priority); } -IOEventRef IOEventLoop::AddWriteEvent(int fd, const std::function<bool()>& callback) { +IOEventRef IOEventLoop::AddWriteEvent(int fd, const std::function<bool()>& callback, + IOEventPriority priority) { if (!MakeFdNonBlocking(fd)) { return nullptr; } - return AddEvent(fd, EV_WRITE | EV_PERSIST, nullptr, callback); + return AddEvent(fd, EV_WRITE | EV_PERSIST, nullptr, callback, priority); } -bool IOEventLoop::AddSignalEvent(int sig, const std::function<bool()>& callback) { - return AddEvent(sig, EV_SIGNAL | EV_PERSIST, nullptr, callback) != nullptr; +bool IOEventLoop::AddSignalEvent(int sig, const std::function<bool()>& callback, + IOEventPriority priority) { + return AddEvent(sig, EV_SIGNAL | EV_PERSIST, nullptr, callback, priority) != nullptr; } -bool IOEventLoop::AddSignalEvents(std::vector<int> sigs, const std::function<bool()>& callback) { +bool IOEventLoop::AddSignalEvents(std::vector<int> sigs, const std::function<bool()>& callback, + IOEventPriority priority) { for (auto sig : sigs) { - if (!AddSignalEvent(sig, callback)) { + if (!AddSignalEvent(sig, callback, priority)) { return false; } } return true; } -IOEventRef IOEventLoop::AddPeriodicEvent(timeval duration, const std::function<bool()>& callback) { - return AddEvent(-1, EV_PERSIST, &duration, callback); +IOEventRef IOEventLoop::AddPeriodicEvent(timeval duration, const std::function<bool()>& callback, + IOEventPriority priority) { + return AddEvent(-1, EV_PERSIST, &duration, callback, priority); } IOEventRef IOEventLoop::AddEvent(int fd_or_sig, int16_t events, timeval* timeout, - const std::function<bool()>& callback) { + const std::function<bool()>& callback, IOEventPriority priority) { if (!EnsureInit()) { return nullptr; } @@ -152,6 +161,7 @@ IOEventRef IOEventLoop::AddEvent(int fd_or_sig, int16_t events, timeval* timeout LOG(ERROR) << "event_new() failed"; return nullptr; } + event_priority_set(e->e, priority); if (event_add(e->e, timeout) != 0) { LOG(ERROR) << "event_add() failed"; return nullptr; diff --git a/simpleperf/IOEventLoop.h b/simpleperf/IOEventLoop.h index 0bbbbd01..1578a4d0 100644 --- a/simpleperf/IOEventLoop.h +++ b/simpleperf/IOEventLoop.h @@ -32,6 +32,12 @@ namespace simpleperf { struct IOEvent; typedef IOEvent* IOEventRef; +enum IOEventPriority { + // Lower value means higher priority. + IOEventHighPriority = 0, + IOEventLowPriority = 1, +}; + // IOEventLoop is a class wrapper of libevent, it monitors events happened, // and calls the corresponding callbacks. Possible events are: file ready to // read, file ready to write, signal happens, periodic timer timeout. @@ -46,22 +52,27 @@ class IOEventLoop { // Register a read Event, so [callback] is called when [fd] can be read // without blocking. If registered successfully, return the reference // to control the Event, otherwise return nullptr. - IOEventRef AddReadEvent(int fd, const std::function<bool()>& callback); + IOEventRef AddReadEvent(int fd, const std::function<bool()>& callback, + IOEventPriority priority = IOEventLowPriority); // Register a write Event, so [callback] is called when [fd] can be written // without blocking. - IOEventRef AddWriteEvent(int fd, const std::function<bool()>& callback); + IOEventRef AddWriteEvent(int fd, const std::function<bool()>& callback, + IOEventPriority priority = IOEventLowPriority); // Register a signal Event, so [callback] is called each time signal [sig] // happens. - bool AddSignalEvent(int sig, const std::function<bool()>& callback); + bool AddSignalEvent(int sig, const std::function<bool()>& callback, + IOEventPriority priority = IOEventLowPriority); // Register a vector of signal Events. - bool AddSignalEvents(std::vector<int> sigs, const std::function<bool()>& callback); + bool AddSignalEvents(std::vector<int> sigs, const std::function<bool()>& callback, + IOEventPriority priority = IOEventLowPriority); // Register a periodic Event, so [callback] is called periodically every // [duration]. - IOEventRef AddPeriodicEvent(timeval duration, const std::function<bool()>& callback); + IOEventRef AddPeriodicEvent(timeval duration, const std::function<bool()>& callback, + IOEventPriority priority = IOEventLowPriority); // Run a loop polling for Events. It only exits when ExitLoop() is called // in a callback function of registered Events. @@ -81,7 +92,8 @@ class IOEventLoop { private: bool EnsureInit(); IOEventRef AddEvent(int fd_or_sig, int16_t events, timeval* timeout, - const std::function<bool()>& callback); + const std::function<bool()>& callback, + IOEventPriority priority = IOEventLowPriority); static void EventCallbackFn(int, int16_t, void*); event_base* ebase_; diff --git a/simpleperf/IOEventLoop_test.cpp b/simpleperf/IOEventLoop_test.cpp index 09f64522..658fe820 100644 --- a/simpleperf/IOEventLoop_test.cpp +++ b/simpleperf/IOEventLoop_test.cpp @@ -250,3 +250,45 @@ TEST(IOEventLoop, exit_before_loop) { IOEventLoop loop; ASSERT_TRUE(loop.ExitLoop()); } + +TEST(IOEventLoop, priority) { + int low_priority_fd[2]; + ASSERT_EQ(0, pipe(low_priority_fd)); + int high_priority_fd[2]; + ASSERT_EQ(0, pipe(high_priority_fd)); + + IOEventLoop loop; + int count = 0; + + ASSERT_NE(nullptr, loop.AddReadEvent( + low_priority_fd[0], + [&]() { + char c; + read(low_priority_fd[0], &c, 1); + CHECK_EQ(count, 1); + count++; + return loop.ExitLoop(); + }, + IOEventLowPriority)); + + ASSERT_NE(nullptr, loop.AddReadEvent( + high_priority_fd[0], + [&]() { + char c; + read(high_priority_fd[0], &c, 1); + CHECK_EQ(count, 0); + count++; + return true; + }, + IOEventHighPriority)); + + char c; + CHECK_EQ(write(low_priority_fd[1], &c, 1), 1); + CHECK_EQ(write(high_priority_fd[1], &c, 1), 1); + ASSERT_TRUE(loop.RunLoop()); + ASSERT_EQ(2, count); + for (int i = 0; i < 2; i++) { + close(low_priority_fd[i]); + close(high_priority_fd[i]); + } +} diff --git a/simpleperf/cmd_monitor.cpp b/simpleperf/cmd_monitor.cpp index ed9edfac..d81ccfea 100644 --- a/simpleperf/cmd_monitor.cpp +++ b/simpleperf/cmd_monitor.cpp @@ -266,21 +266,22 @@ bool MonitorCommand::PrepareMonitoring() { // 5. Add read/signal/periodic Events. IOEventLoop* loop = event_selection_set_.GetIOEventLoop(); auto exit_loop_callback = [loop]() { return loop->ExitLoop(); }; - if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback)) { + if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback, IOEventHighPriority)) { return false; } // Only add an event for SIGHUP if we didn't inherit SIG_IGN (e.g. from // nohup). if (!SignalIsIgnored(SIGHUP)) { - if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback)) { + if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback, IOEventHighPriority)) { return false; } } if (duration_in_sec_ != 0) { - if (!loop->AddPeriodicEvent(SecondToTimeval(duration_in_sec_), - [loop]() { return loop->ExitLoop(); })) { + if (!loop->AddPeriodicEvent( + SecondToTimeval(duration_in_sec_), [loop]() { return loop->ExitLoop(); }, + IOEventHighPriority)) { return false; } } @@ -291,6 +292,10 @@ bool MonitorCommand::DoMonitoring() { if (!event_selection_set_.GetIOEventLoop()->RunLoop()) { return false; } + if (!event_selection_set_.SyncKernelBuffer()) { + return false; + } + event_selection_set_.CloseEventFiles(); if (!event_selection_set_.FinishReadMmapEventData()) { return false; } diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index b84bcfab..35cab822 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -629,25 +629,26 @@ bool RecordCommand::PrepareRecording(Workload* workload) { } IOEventLoop* loop = event_selection_set_.GetIOEventLoop(); auto exit_loop_callback = [loop]() { return loop->ExitLoop(); }; - if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback)) { + if (!loop->AddSignalEvents({SIGCHLD, SIGINT, SIGTERM}, exit_loop_callback, IOEventHighPriority)) { return false; } // Only add an event for SIGHUP if we didn't inherit SIG_IGN (e.g. from nohup). if (!SignalIsIgnored(SIGHUP)) { - if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback)) { + if (!loop->AddSignalEvent(SIGHUP, exit_loop_callback, IOEventHighPriority)) { return false; } } if (stop_signal_fd_ != -1) { - if (!loop->AddReadEvent(stop_signal_fd_, exit_loop_callback)) { + if (!loop->AddReadEvent(stop_signal_fd_, exit_loop_callback, IOEventHighPriority)) { return false; } } if (duration_in_sec_ != 0) { - if (!loop->AddPeriodicEvent(SecondToTimeval(duration_in_sec_), - [loop]() { return loop->ExitLoop(); })) { + if (!loop->AddPeriodicEvent( + SecondToTimeval(duration_in_sec_), [loop]() { return loop->ExitLoop(); }, + IOEventHighPriority)) { return false; } } @@ -718,9 +719,10 @@ bool RecordCommand::DoRecording(Workload* workload) { return false; } time_stat_.stop_recording_time = GetSystemClock(); - if (!event_selection_set_.FinishReadMmapEventData()) { + if (!event_selection_set_.SyncKernelBuffer()) { return false; } + event_selection_set_.CloseEventFiles(); time_stat_.finish_recording_time = GetSystemClock(); uint64_t recording_time = time_stat_.finish_recording_time - time_stat_.start_recording_time; LOG(INFO) << "Recorded for " << recording_time / 1e9 << " seconds. Start post processing."; @@ -754,26 +756,31 @@ static bool WriteRecordDataToOutFd(const std::string& in_filename, } bool RecordCommand::PostProcessRecording(const std::vector<std::string>& args) { - // 1. Merge map records dumped while recording by map record thread. + // 1. Read records left in the buffer. + if (!event_selection_set_.FinishReadMmapEventData()) { + return false; + } + + // 2. Merge map records dumped while recording by map record thread. if (map_record_thread_) { if (!map_record_thread_->Join() || !MergeMapRecords()) { return false; } } - // 2. Post unwind dwarf callchain. + // 3. Post unwind dwarf callchain. if (unwind_dwarf_callchain_ && post_unwind_) { if (!PostUnwindRecords()) { return false; } } - // 3. Optionally join Callchains. + // 4. Optionally join Callchains. if (callchain_joiner_) { JoinCallChains(); } - // 4. Dump additional features, and close record file. + // 5. Dump additional features, and close record file. if (!DumpAdditionalFeatures(args)) { return false; } @@ -785,7 +792,7 @@ bool RecordCommand::PostProcessRecording(const std::vector<std::string>& args) { } time_stat_.post_process_time = GetSystemClock(); - // 4. Show brief record result. + // 6. Show brief record result. auto record_stat = event_selection_set_.GetRecordStat(); if (event_selection_set_.HasAuxTrace()) { LOG(INFO) << "Aux data traced: " << record_stat.aux_data_size; diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp index d5bca318..58b4b956 100644 --- a/simpleperf/event_selection_set.cpp +++ b/simpleperf/event_selection_set.cpp @@ -840,14 +840,7 @@ bool EventSelectionSet::ReadMmapEventData(bool with_time_limit) { } bool EventSelectionSet::FinishReadMmapEventData() { - // Stop the read thread, so we don't get more records beyond current time. - if (!SyncKernelBuffer() || !record_read_thread_->StopReadThread()) { - return false; - } - if (!ReadMmapEventData(false)) { - return false; - } - return true; + return ReadMmapEventData(false); } void EventSelectionSet::CloseEventFiles() { |