diff options
author | Treehugger Robot <treehugger-gerrit@google.com> | 2016-07-14 02:17:21 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2016-07-14 02:17:21 +0000 |
commit | e5b5cf07c7c092a178f25dadff8842e9000d0e1f (patch) | |
tree | dc33c5ced54dc2d16c0f794a0d33ee9f12f9807e | |
parent | 7a6b3fdff5ef275b19811c48d4e999c04106ad6a (diff) | |
parent | 0a072cda021e5dfbdbb39f4d8d30771a851b3c3a (diff) | |
download | extras-e5b5cf07c7c092a178f25dadff8842e9000d0e1f.tar.gz |
Merge "simpleperf: adjust mapped buffer size in record command."android-wear-7.1.1_r1android-n-preview-5android-n-iot-preview-2nougat-mr1-wear-releasen-iot-preview-2
-rw-r--r-- | simpleperf/cmd_record.cpp | 29 | ||||
-rw-r--r-- | simpleperf/event_fd.cpp | 38 | ||||
-rw-r--r-- | simpleperf/event_fd.h | 6 | ||||
-rw-r--r-- | simpleperf/event_selection_set.cpp | 29 | ||||
-rw-r--r-- | simpleperf/event_selection_set.h | 3 |
5 files changed, 71 insertions, 34 deletions
diff --git a/simpleperf/cmd_record.cpp b/simpleperf/cmd_record.cpp index 050ca854..9690e1d3 100644 --- a/simpleperf/cmd_record.cpp +++ b/simpleperf/cmd_record.cpp @@ -65,6 +65,11 @@ constexpr uint64_t DEFAULT_SAMPLE_PERIOD_FOR_TRACEPOINT_EVENT = 1; // should be a multiply of 8, so MAX_DUMP_STACK_SIZE is 65528. constexpr uint32_t MAX_DUMP_STACK_SIZE = 65528; +// The max allowed pages in mapped buffer is decided by rlimit(RLIMIT_MEMLOCK). +// Here 1024 is a desired value for pages in mapped buffer. If mapped +// successfully, the buffer size = 1024 * 4K (page size) = 4M. +constexpr size_t DESIRED_PAGES_IN_MAPPED_BUFFER = 1024; + class RecordCommand : public Command { public: RecordCommand() @@ -117,9 +122,8 @@ class RecordCommand : public Command { " This option requires at least one branch type among any, any_call,\n" " any_ret, ind_call.\n" "-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. The default value for\n" -" system wide profiling is 256. The default value for non system\n" -" wide profiling is 128.\n" +" the kernel. It should be a power of 2. If not set, the max\n" +" possible value <= 1024 will be used.\n" "--no-dump-kernel-symbols Don't dump kernel symbols in perf.data. By default\n" " kernel symbols will be dumped when needed.\n" "--no-inherit Don't record created child threads/processes.\n" @@ -153,7 +157,7 @@ class RecordCommand : public Command { child_inherit_(true), can_dump_kernel_symbols_(true), dump_symbols_(false), - perf_mmap_pages_(0), + mmap_page_range_(std::make_pair(1, DESIRED_PAGES_IN_MAPPED_BUFFER)), record_filename_("perf.data"), sample_record_count_(0), lost_record_count_(0) { @@ -206,8 +210,7 @@ class RecordCommand : public Command { std::vector<int> cpus_; EventSelectionSet event_selection_set_; - // mmap pages used by each perf event file, should be a power of 2. - size_t perf_mmap_pages_; + std::pair<size_t, size_t> mmap_page_range_; ThreadTree thread_tree_; std::string record_filename_; @@ -254,7 +257,7 @@ bool RecordCommand::Run(const std::vector<std::string>& args) { event_selection_set_.SetEnableOnExec(true); } else { LOG(ERROR) - << "No threads to monitor. Try `simpleperf help record` for help\n"; + << "No threads to monitor. Try `simpleperf help record` for help"; return false; } } @@ -272,7 +275,8 @@ bool RecordCommand::Run(const std::vector<std::string>& args) { } } std::vector<pollfd> pollfds; - if (!event_selection_set_.MmapEventFiles(perf_mmap_pages_, &pollfds)) { + if (!event_selection_set_.MmapEventFiles(mmap_page_range_.first, + mmap_page_range_.second, &pollfds)) { return false; } @@ -335,7 +339,6 @@ bool RecordCommand::Run(const std::vector<std::string>& args) { bool RecordCommand::ParseOptions(const std::vector<std::string>& args, std::vector<std::string>* non_option_args) { std::set<pid_t> tid_set; - size_t mmap_pages = 0; size_t i; for (i = 0; i < args.size() && !args[i].empty() && args[i][0] == '-'; ++i) { if (args[i] == "-a") { @@ -454,7 +457,7 @@ bool RecordCommand::ParseOptions(const std::vector<std::string>& args, LOG(ERROR) << "Invalid mmap_pages: '" << args[i] << "'"; return false; } - mmap_pages = pages; + mmap_page_range_.first = mmap_page_range_.second = pages; } else if (args[i] == "--no-dump-kernel-symbols") { can_dump_kernel_symbols_ = false; } else if (args[i] == "--no-inherit") { @@ -538,12 +541,6 @@ bool RecordCommand::ParseOptions(const std::vector<std::string>& args, can_dump_kernel_symbols_ = false; } - if (mmap_pages != 0) { - perf_mmap_pages_ = mmap_pages; - } else { - perf_mmap_pages_ = (system_wide_collection_ ? 256 : 128); - } - if (non_option_args != nullptr) { non_option_args->clear(); for (; i < args.size(); ++i) { diff --git a/simpleperf/event_fd.cpp b/simpleperf/event_fd.cpp index 2fd4d522..0002d02e 100644 --- a/simpleperf/event_fd.cpp +++ b/simpleperf/event_fd.cpp @@ -76,9 +76,7 @@ std::unique_ptr<EventFd> EventFd::OpenEventFile(const perf_event_attr& attr, pid } EventFd::~EventFd() { - if (mmap_addr_ != nullptr) { - munmap(mmap_addr_, mmap_len_); - } + DestroyMappedBuffer(); close(perf_event_fd_); } @@ -115,19 +113,22 @@ bool EventFd::ReadCounter(PerfCounter* counter) const { return true; } -bool EventFd::CreateMappedBuffer(size_t mmap_pages, pollfd* poll_fd) { +bool EventFd::CreateMappedBuffer(size_t mmap_pages, pollfd* poll_fd, bool report_error) { CHECK(IsPowerOfTwo(mmap_pages)); size_t page_size = sysconf(_SC_PAGE_SIZE); size_t mmap_len = (mmap_pages + 1) * page_size; void* mmap_addr = mmap(nullptr, mmap_len, PROT_READ | PROT_WRITE, MAP_SHARED, perf_event_fd_, 0); if (mmap_addr == MAP_FAILED) { bool is_perm_error = (errno == EPERM); - PLOG(ERROR) << "mmap() failed for " << Name(); - if (is_perm_error) { + if (report_error) { + PLOG(ERROR) << "mmap(" << mmap_pages << ") failed for " << Name(); + } else { + PLOG(DEBUG) << "mmap(" << mmap_pages << ") failed for " << Name(); + } + if (report_error && is_perm_error) { LOG(ERROR) << "It seems the kernel doesn't allow allocating enough " - << "buffer for dumping samples, consider decreasing the number of " - << "monitored threads(-t), or decreasing mmap pages(-m), or " - << "decreasing the number of events(-e)."; + << "buffer for dumping samples, consider decreasing mmap pages(-m), " + << "or decreasing the number of events(-e)."; } return false; } @@ -145,18 +146,31 @@ bool EventFd::CreateMappedBuffer(size_t mmap_pages, pollfd* poll_fd) { return true; } -bool EventFd::ShareMappedBuffer(const EventFd& event_fd) { +bool EventFd::ShareMappedBuffer(const EventFd& event_fd, bool report_error) { CHECK(!HasMappedBuffer()); CHECK(event_fd.HasMappedBuffer()); int result = ioctl(perf_event_fd_, PERF_EVENT_IOC_SET_OUTPUT, event_fd.perf_event_fd_); if (result != 0) { - PLOG(ERROR) << "failed to share mapped buffer of " - << event_fd.perf_event_fd_ << " with " << perf_event_fd_; + if (report_error) { + PLOG(ERROR) << "failed to share mapped buffer of " + << event_fd.perf_event_fd_ << " with " << perf_event_fd_; + } return false; } return true; } +void EventFd::DestroyMappedBuffer() { + if (HasMappedBuffer()) { + munmap(mmap_addr_, mmap_len_); + mmap_addr_ = nullptr; + mmap_len_ = 0; + mmap_metadata_page_ = nullptr; + mmap_data_buffer_ = nullptr; + mmap_data_buffer_size_ = 0; + } +} + size_t EventFd::GetAvailableMmapData(char** pdata) { if (!HasMappedBuffer()) { return 0; diff --git a/simpleperf/event_fd.h b/simpleperf/event_fd.h index 651f3fd4..d33368cb 100644 --- a/simpleperf/event_fd.h +++ b/simpleperf/event_fd.h @@ -65,16 +65,18 @@ class EventFd { // Create mapped buffer used to receive records sent by the kernel. // mmap_pages should be power of 2. If created successfully, fill pollfd, // which is used to poll() on available mapped data. - bool CreateMappedBuffer(size_t mmap_pages, pollfd* poll_fd); + bool CreateMappedBuffer(size_t mmap_pages, pollfd* poll_fd, bool report_error); // Share the mapped buffer used by event_fd. The two EventFds should monitor // the same event on the same cpu, but have different thread ids. - bool ShareMappedBuffer(const EventFd& event_fd); + bool ShareMappedBuffer(const EventFd& event_fd, bool report_error); bool HasMappedBuffer() const { return mmap_data_buffer_size_ != 0; } + void DestroyMappedBuffer(); + // When the kernel writes new sampled records to the mapped area, we can get them by returning // the start address and size of the data. size_t GetAvailableMmapData(char** pdata); diff --git a/simpleperf/event_selection_set.cpp b/simpleperf/event_selection_set.cpp index 267f40d1..5a98fd28 100644 --- a/simpleperf/event_selection_set.cpp +++ b/simpleperf/event_selection_set.cpp @@ -335,7 +335,29 @@ bool EventSelectionSet::ReadCounters(std::vector<CountersInfo>* counters) { return true; } -bool EventSelectionSet::MmapEventFiles(size_t mmap_pages, std::vector<pollfd>* pollfds) { +bool EventSelectionSet::MmapEventFiles(size_t min_mmap_pages, + size_t max_mmap_pages, + std::vector<pollfd>* pollfds) { + for (size_t i = max_mmap_pages; i >= min_mmap_pages; i >>= 1) { + if (MmapEventFiles(i, pollfds, i == min_mmap_pages)) { + LOG(VERBOSE) << "Mapped buffer size is " << i << " pages."; + return true; + } + for (auto& group : groups_) { + for (auto& selection : group) { + for (auto& event_fd : selection.event_fds) { + event_fd->DestroyMappedBuffer(); + } + } + } + } + return false; +} + +bool EventSelectionSet::MmapEventFiles(size_t mmap_pages, + std::vector<pollfd>* pollfds, + bool report_error) { + pollfds->clear(); for (auto& group : groups_) { for (auto& selection : group) { // For each event, allocate a mapped buffer for each cpu. @@ -343,12 +365,13 @@ bool EventSelectionSet::MmapEventFiles(size_t mmap_pages, std::vector<pollfd>* p for (auto& event_fd : selection.event_fds) { auto it = cpu_map.find(event_fd->Cpu()); if (it != cpu_map.end()) { - if (!event_fd->ShareMappedBuffer(*(it->second))) { + if (!event_fd->ShareMappedBuffer(*(it->second), report_error)) { return false; } } else { pollfd poll_fd; - if (!event_fd->CreateMappedBuffer(mmap_pages, &poll_fd)) { + if (!event_fd->CreateMappedBuffer(mmap_pages, &poll_fd, + report_error)) { return false; } pollfds->push_back(poll_fd); diff --git a/simpleperf/event_selection_set.h b/simpleperf/event_selection_set.h index 87bdeab7..5af8c0c1 100644 --- a/simpleperf/event_selection_set.h +++ b/simpleperf/event_selection_set.h @@ -88,7 +88,7 @@ class EventSelectionSet { bool OpenEventFilesForCpus(const std::vector<int>& cpus); bool OpenEventFilesForThreadsOnCpus(const std::vector<pid_t>& threads, std::vector<int> cpus); bool ReadCounters(std::vector<CountersInfo>* counters); - bool MmapEventFiles(size_t mmap_pages, std::vector<pollfd>* pollfds); + bool MmapEventFiles(size_t min_mmap_pages, size_t max_mmap_pages, std::vector<pollfd>* pollfds); void PrepareToReadMmapEventData(std::function<bool (Record*)> callback); bool ReadMmapEventData(); bool FinishReadMmapEventData(); @@ -98,6 +98,7 @@ class EventSelectionSet { EventSelection* selection); void UnionSampleType(); bool OpenEventFiles(const std::vector<pid_t>& threads, const std::vector<int>& cpus); + bool MmapEventFiles(size_t mmap_pages, std::vector<pollfd>* pollfds, bool report_error); bool ReadMmapEventDataForFd(std::unique_ptr<EventFd>& event_fd, const perf_event_attr& attr, bool* has_data); |