diff options
author | Yabin Cui <yabinc@google.com> | 2019-08-08 18:04:17 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-08-08 18:04:17 -0700 |
commit | 77605b5b77f55fd870a243d790de52564c0d6ae6 (patch) | |
tree | fe09a575f762725be53116b97c933f564caf15c3 | |
parent | 746d8d3b95ec38e47f37c0a5d41b47e329211488 (diff) | |
parent | f36aa2b28a503e6ba57367d52b8cbda2de2d06af (diff) | |
download | extras-77605b5b77f55fd870a243d790de52564c0d6ae6.tar.gz |
Merge "simpleperf: add --aux-buffer-size in record cmd."
am: f36aa2b28a
Change-Id: Ifac3113a2ba15fa0cb45d9afc8eaa88851286c99
-rw-r--r-- | simpleperf/RecordReadThread.cpp | 15 | ||||
-rw-r--r-- | simpleperf/RecordReadThread.h | 4 | ||||
-rw-r--r-- | simpleperf/RecordReadThread_test.cpp | 16 | ||||
-rw-r--r-- | simpleperf/cmd_record.cpp | 25 | ||||
-rw-r--r-- | simpleperf/cmd_record_test.cpp | 12 | ||||
-rw-r--r-- | simpleperf/event_selection_set.cpp | 9 | ||||
-rw-r--r-- | simpleperf/event_selection_set.h | 4 |
7 files changed, 62 insertions, 23 deletions
diff --git a/simpleperf/RecordReadThread.cpp b/simpleperf/RecordReadThread.cpp index e2a6d417..b89066b9 100644 --- a/simpleperf/RecordReadThread.cpp +++ b/simpleperf/RecordReadThread.cpp @@ -32,9 +32,6 @@ namespace simpleperf { static constexpr size_t kDefaultLowBufferLevel = 10 * 1024 * 1024u; static constexpr size_t kDefaultCriticalBufferLevel = 5 * 1024 * 1024u; -// TODO: add an option to config it. -static constexpr size_t kDefaultAuxBufferSize = 4 * 1024 * 1024; - RecordBuffer::RecordBuffer(size_t buffer_size) : read_head_(0), write_head_(0), buffer_size_(buffer_size), buffer_(new char[buffer_size]) { } @@ -210,9 +207,13 @@ bool KernelRecordReader::MoveToNextRecord(const RecordParser& parser) { RecordReadThread::RecordReadThread(size_t record_buffer_size, const perf_event_attr& attr, size_t min_mmap_pages, size_t max_mmap_pages, - bool allow_cutting_samples) - : record_buffer_(record_buffer_size), record_parser_(attr), attr_(attr), - min_mmap_pages_(min_mmap_pages), max_mmap_pages_(max_mmap_pages) { + size_t aux_buffer_size, bool allow_cutting_samples) + : record_buffer_(record_buffer_size), + record_parser_(attr), + attr_(attr), + min_mmap_pages_(min_mmap_pages), + max_mmap_pages_(max_mmap_pages), + aux_buffer_size_(aux_buffer_size) { if (attr.sample_type & PERF_SAMPLE_STACK_USER) { stack_size_in_sample_record_ = attr.sample_stack_user; } @@ -375,7 +376,7 @@ bool RecordReadThread::HandleAddEventFds(IOEventLoop& loop, break; } if (IsEtmEventType(fd->attr().type)) { - if (!fd->CreateAuxBuffer(kDefaultAuxBufferSize, report_error)) { + if (!fd->CreateAuxBuffer(aux_buffer_size_, report_error)) { fd->DestroyMappedBuffer(); success = false; break; diff --git a/simpleperf/RecordReadThread.h b/simpleperf/RecordReadThread.h index a12cf372..4e93f97a 100644 --- a/simpleperf/RecordReadThread.h +++ b/simpleperf/RecordReadThread.h @@ -124,7 +124,8 @@ class KernelRecordReader { class RecordReadThread { public: RecordReadThread(size_t record_buffer_size, const perf_event_attr& attr, size_t min_mmap_pages, - size_t max_mmap_pages, bool allow_cutting_samples = true); + size_t max_mmap_pages, size_t aux_buffer_size, + bool allow_cutting_samples = true); ~RecordReadThread(); void SetBufferLevels(size_t record_buffer_low_level, size_t record_buffer_critical_level) { record_buffer_low_level_ = record_buffer_low_level; @@ -184,6 +185,7 @@ class RecordReadThread { size_t stack_size_in_sample_record_ = 0; size_t min_mmap_pages_; size_t max_mmap_pages_; + size_t aux_buffer_size_; // Used to pass command notification from the main thread to the read thread. android::base::unique_fd write_cmd_fd_; diff --git a/simpleperf/RecordReadThread_test.cpp b/simpleperf/RecordReadThread_test.cpp index 6dcec3bd..eae58345 100644 --- a/simpleperf/RecordReadThread_test.cpp +++ b/simpleperf/RecordReadThread_test.cpp @@ -243,7 +243,7 @@ TEST_F(RecordReadThreadTest, handle_cmds) { perf_event_attr attr = CreateFakeEventAttr(); records_ = CreateFakeRecords(attr, 2, 0, 0); std::vector<EventFd*> event_fds = CreateFakeEventFds(attr, 2); - RecordReadThread thread(128 * 1024, event_fds[0]->attr(), 1, 1); + RecordReadThread thread(128 * 1024, event_fds[0]->attr(), 1, 1, 0); IOEventLoop loop; bool has_notify = false; auto callback = [&]() { @@ -262,7 +262,7 @@ TEST_F(RecordReadThreadTest, handle_cmds) { TEST_F(RecordReadThreadTest, read_records) { perf_event_attr attr = CreateFakeEventAttr(); - RecordReadThread thread(128 * 1024, attr, 1, 1); + RecordReadThread thread(128 * 1024, attr, 1, 1, 0); IOEventLoop loop; size_t record_index; auto callback = [&]() { @@ -297,7 +297,7 @@ TEST_F(RecordReadThreadTest, process_sample_record) { attr.sample_type |= PERF_SAMPLE_STACK_USER; attr.sample_stack_user = 64 * 1024; size_t record_buffer_size = 128 * 1024; - RecordReadThread thread(record_buffer_size, attr, 1, 1); + RecordReadThread thread(record_buffer_size, attr, 1, 1, 0); IOEventLoop loop; ASSERT_TRUE(thread.RegisterDataCallback(loop, []() { return true; })); @@ -348,7 +348,7 @@ TEST_F(RecordReadThreadTest, process_sample_record) { // records even if reading one record at a time. TEST_F(RecordReadThreadTest, has_data_notification_until_buffer_empty) { perf_event_attr attr = CreateFakeEventAttr(); - RecordReadThread thread(128 * 1024, attr, 1, 1); + RecordReadThread thread(128 * 1024, attr, 1, 1, 0); IOEventLoop loop; size_t record_index = 0; auto read_one_record = [&]() { @@ -376,7 +376,7 @@ TEST_F(RecordReadThreadTest, no_cut_samples) { perf_event_attr attr = CreateFakeEventAttr(); attr.sample_type |= PERF_SAMPLE_STACK_USER; attr.sample_stack_user = 64 * 1024; - RecordReadThread thread(128 * 1024, attr, 1, 1, false); + RecordReadThread thread(128 * 1024, attr, 1, 1, 0, false); IOEventLoop loop; ASSERT_TRUE(thread.RegisterDataCallback(loop, []() { return true; })); const size_t total_samples = 100; @@ -438,10 +438,12 @@ TEST_F(RecordReadThreadTest, read_aux_data) { return size == aux_data[test_index].buf1.size() + aux_data[test_index].buf2.size(); }; + const size_t AUX_BUFFER_SIZE = 4096; + perf_event_attr attr = CreateDefaultPerfEventAttr(*type); MockEventFd fd(attr, 0, nullptr, 1, true); EXPECT_CALL(fd, CreateMappedBuffer(_, _)).Times(1).WillOnce(Return(true)); - EXPECT_CALL(fd, CreateAuxBuffer(_, _)).Times(1).WillOnce(Return(true)); + EXPECT_CALL(fd, CreateAuxBuffer(Eq(AUX_BUFFER_SIZE), _)).Times(1).WillOnce(Return(true)); EXPECT_CALL(fd, StartPolling(_, _)).Times(1).WillOnce(Return(true)); EXPECT_CALL(fd, GetAvailableMmapDataSize(_)).Times(aux_data.size()).WillRepeatedly(Return(0)); EXPECT_CALL(fd, @@ -452,7 +454,7 @@ TEST_F(RecordReadThreadTest, read_aux_data) { EXPECT_CALL(fd, DestroyMappedBuffer()).Times(1); EXPECT_CALL(fd, DestroyAuxBuffer()).Times(1); - RecordReadThread thread(1024, attr, 1, 1); + RecordReadThread thread(1024, attr, 1, 1, AUX_BUFFER_SIZE); IOEventLoop loop; ASSERT_TRUE(thread.RegisterDataCallback(loop, []() { return true; })); ASSERT_TRUE(thread.AddEventFds({&fd})); diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 082b6939..7641c40e 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -93,6 +93,8 @@ constexpr size_t DEFAULT_CALL_CHAIN_JOINER_CACHE_SIZE = 8 * 1024 * 1024; static constexpr size_t kRecordBufferSize = 64 * 1024 * 1024; static constexpr size_t kSystemWideRecordBufferSize = 256 * 1024 * 1024; +static constexpr size_t kDefaultAuxBufferSize = 4 * 1024 * 1024; + struct TimeStat { uint64_t prepare_recording_time = 0; uint64_t start_recording_time = 0; @@ -180,6 +182,10 @@ class RecordCommand : public Command { "-m mmap_pages Set the size of the buffer used to receiving sample data from\n" " the kernel. It should be a power of 2. If not set, the max\n" " possible value <= 1024 will be used.\n" +"--aux-buffer-size <buffer_size> Set aux buffer size, only used in cs-etm event type.\n" +" Need to be power of 2 and page size aligned.\n" +" Used memory size is (buffer_size * (cpu_count + 1).\n" +" Default is 4M.\n" "--no-inherit Don't record created child threads/processes.\n" "--cpu-percent <percent> Set the max percent of cpu time used for recording.\n" " percent is in range [1-100], default is 25.\n" @@ -321,6 +327,7 @@ class RecordCommand : public Command { EventSelectionSet event_selection_set_; std::pair<size_t, size_t> mmap_page_range_; + size_t aux_buffer_size_ = kDefaultAuxBufferSize; ThreadTree thread_tree_; std::string record_filename_; @@ -477,7 +484,8 @@ bool RecordCommand::PrepareRecording(Workload* workload) { size_t record_buffer_size = system_wide_collection_ ? kSystemWideRecordBufferSize : kRecordBufferSize; if (!event_selection_set_.MmapEventFiles(mmap_page_range_.first, mmap_page_range_.second, - record_buffer_size, allow_cutting_samples_)) { + aux_buffer_size_, record_buffer_size, + allow_cutting_samples_)) { return false; } auto callback = @@ -686,6 +694,15 @@ bool RecordCommand::ParseOptions(const std::vector<std::string>& args, return false; } app_package_name_ = args[i]; + } else if (args[i] == "--aux-buffer-size") { + if (!GetUintOption(args, &i, &aux_buffer_size_, 0, std::numeric_limits<size_t>::max(), + true)) { + return false; + } + if (!IsPowerOfTwo(aux_buffer_size_) || aux_buffer_size_ % sysconf(_SC_PAGE_SIZE)) { + LOG(ERROR) << "invalid aux buffer size: " << args[i]; + return false; + } } else if (args[i] == "-b") { branch_sampling_ = branch_sampling_type_map["any"]; } else if (args[i] == "-c" || args[i] == "-f") { @@ -992,7 +1009,11 @@ bool RecordCommand::AdjustPerfEventLimit() { set_prop = true; } // 3. Adjust perf_event_mlock_kb. - uint64_t mlock_kb = sysconf(_SC_NPROCESSORS_CONF) * (mmap_page_range_.second + 1) * 4; + long cpus = sysconf(_SC_NPROCESSORS_CONF); + uint64_t mlock_kb = cpus * (mmap_page_range_.second + 1) * 4; + if (event_selection_set_.HasAuxTrace()) { + mlock_kb += cpus * aux_buffer_size_ / 1024; + } uint64_t cur_mlock_kb; if (GetPerfEventMlockKb(&cur_mlock_kb) && cur_mlock_kb < mlock_kb && !SetPerfEventMlockKb(mlock_kb)) { diff --git a/simpleperf/cmd_record_test.cpp b/simpleperf/cmd_record_test.cpp index 3e2351de..1821913e 100644 --- a/simpleperf/cmd_record_test.cpp +++ b/simpleperf/cmd_record_test.cpp @@ -828,4 +828,16 @@ TEST(record_cmd, cs_etm_event) { ASSERT_TRUE(has_auxtrace_info); ASSERT_TRUE(has_auxtrace); ASSERT_TRUE(has_aux); +} + +TEST(record_cmd, aux_buffer_size_option) { + if (!ETMRecorder::GetInstance().CheckEtmSupport()) { + GTEST_LOG_(INFO) << "Omit this test since etm isn't supported on this device"; + return; + } + ASSERT_TRUE(RunRecordCmd({"-e", "cs-etm", "--aux-buffer-size", "1m"})); + // not page size aligned + ASSERT_FALSE(RunRecordCmd({"-e", "cs-etm", "--aux-buffer-size", "1024"})); + // not power of two + ASSERT_FALSE(RunRecordCmd({"-e", "cs-etm", "--aux-buffer-size", "12k"})); }
\ No newline at end of file diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp index 6855392e..1e7f790d 100644 --- a/simpleperf/event_selection_set.cpp +++ b/simpleperf/event_selection_set.cpp @@ -623,10 +623,11 @@ bool EventSelectionSet::ReadCounters(std::vector<CountersInfo>* counters) { } bool EventSelectionSet::MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages, - size_t record_buffer_size, bool allow_cutting_samples) { - record_read_thread_.reset(new simpleperf::RecordReadThread( - record_buffer_size, groups_[0][0].event_attr, min_mmap_pages, max_mmap_pages, - allow_cutting_samples)); + size_t aux_buffer_size, size_t record_buffer_size, + bool allow_cutting_samples) { + record_read_thread_.reset( + new simpleperf::RecordReadThread(record_buffer_size, groups_[0][0].event_attr, min_mmap_pages, + max_mmap_pages, aux_buffer_size, allow_cutting_samples)); return true; } diff --git a/simpleperf/event_selection_set.h b/simpleperf/event_selection_set.h index f9f38ad2..426af2f2 100644 --- a/simpleperf/event_selection_set.h +++ b/simpleperf/event_selection_set.h @@ -132,8 +132,8 @@ class EventSelectionSet { bool OpenEventFiles(const std::vector<int>& on_cpus); bool ReadCounters(std::vector<CountersInfo>* counters); - bool MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages, size_t record_buffer_size, - bool allow_cutting_samples); + bool MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages, size_t aux_buffer_size, + size_t record_buffer_size, bool allow_cutting_samples); bool PrepareToReadMmapEventData(const std::function<bool(Record*)>& callback); bool SyncKernelBuffer(); bool FinishReadMmapEventData(); |