meminfo: Add support to track working set with idle page tracking.
Also adds a tool to make use of this if it exists call 'wsstop'
Bug: 111694435
Test: wsstop -d 3 -n 100 1
Change-Id: I50415f0bdc09c09b5b414cf0e4fff8f2907c5823
Signed-off-by: Sandeep Patil <sspatil@google.com>
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index 1df03b2..069b6b3 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -121,6 +121,14 @@
return maps_;
}
+const std::vector<Vma>& ProcMemInfo::MapsWithPageIdle() {
+ if (maps_.empty() && !ReadMaps(get_wss_, true)) {
+ LOG(ERROR) << "Failed to read maps with page idle for Process " << pid_;
+ }
+
+ return maps_;
+}
+
const std::vector<Vma>& ProcMemInfo::Smaps(const std::string& path) {
if (!maps_.empty()) {
return maps_;
@@ -226,7 +234,7 @@
return true;
}
-bool ProcMemInfo::ReadMaps(bool get_wss) {
+bool ProcMemInfo::ReadMaps(bool get_wss, bool use_pageidle) {
// Each object reads /proc/<pid>/maps only once. This is done to make sure programs that are
// running for the lifetime of the system can recycle the objects and don't have to
// unnecessarily retain and update this object in memory (which can get significantly large).
@@ -256,7 +264,7 @@
}
for (auto& vma : maps_) {
- if (!ReadVmaStats(pagemap_fd.get(), vma, get_wss)) {
+ if (!ReadVmaStats(pagemap_fd.get(), vma, get_wss, use_pageidle)) {
LOG(ERROR) << "Failed to read page map for vma " << vma.name << "[" << vma.start << "-"
<< vma.end << "]";
maps_.clear();
@@ -268,7 +276,7 @@
return true;
}
-bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss) {
+bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss, bool use_pageidle) {
PageAcct& pinfo = PageAcct::Instance();
uint64_t pagesz = getpagesize();
uint64_t num_pages = (vma.end - vma.start) / pagesz;
@@ -281,6 +289,13 @@
return false;
}
+ if (get_wss && use_pageidle) {
+ if (!pinfo.InitPageAcct(true)) {
+ LOG(ERROR) << "Failed to init idle page accounting";
+ return false;
+ }
+ }
+
std::unique_ptr<uint64_t[]> pg_flags(new uint64_t[num_pages]);
std::unique_ptr<uint64_t[]> pg_counts(new uint64_t[num_pages]);
for (uint64_t i = 0; i < num_pages; ++i) {
@@ -323,7 +338,8 @@
bool is_private = (pg_counts[i] == 1);
// Working set
if (get_wss) {
- bool is_referenced = !!(pg_flags[i] & (1 << KPF_REFERENCED));
+ bool is_referenced = use_pageidle ? (pinfo.IsPageIdle(page_frame) == 1)
+ : !!(pg_flags[i] & (1 << KPF_REFERENCED));
if (!is_referenced) {
continue;
}