summaryrefslogtreecommitdiffstats
path: root/libmeminfo
diff options
context:
space:
mode:
authorSandeep Patil <sspatil@google.com>2018-11-09 16:42:45 -0800
committerSandeep Patil <sspatil@google.com>2018-12-04 14:02:28 -0800
commit2259fdf7df44bc94cf03b955d9a97b30c5e7c490 (patch)
treea30815a9d9d6b07bafd5b302dbe0775cea5c6c72 /libmeminfo
parent5cd79691770ae774c7b07a15453b6d63aedbe1fc (diff)
downloadsystem_core-2259fdf7df44bc94cf03b955d9a97b30c5e7c490.tar.gz
system_core-2259fdf7df44bc94cf03b955d9a97b30c5e7c490.tar.bz2
system_core-2259fdf7df44bc94cf03b955d9a97b30c5e7c490.zip
libmeminfo: Add support for counting swap pages
Adds procmeminfo API to get the vector of swap_offsets if SWAP is enabled on the device. Bug: 114325007 Bug: 111694435 Test: libmeminfo_test 1 Change-Id: If0b52d042749a5bcb2c87aa2cb1595190d4769b1 Signed-off-by: Sandeep Patil <sspatil@google.com>
Diffstat (limited to 'libmeminfo')
-rw-r--r--libmeminfo/include/meminfo/meminfo.h5
-rw-r--r--libmeminfo/include/meminfo/procmeminfo.h2
-rw-r--r--libmeminfo/include/meminfo/sysmeminfo.h46
-rw-r--r--libmeminfo/libmeminfo_test.cpp26
-rw-r--r--libmeminfo/procmeminfo.cpp13
-rw-r--r--libmeminfo/sysmeminfo.cpp12
6 files changed, 80 insertions, 24 deletions
diff --git a/libmeminfo/include/meminfo/meminfo.h b/libmeminfo/include/meminfo/meminfo.h
index c328648f3..809054bd8 100644
--- a/libmeminfo/include/meminfo/meminfo.h
+++ b/libmeminfo/include/meminfo/meminfo.h
@@ -31,6 +31,8 @@ struct MemUsage {
uint64_t pss;
uint64_t uss;
+ uint64_t swap;
+
uint64_t private_clean;
uint64_t private_dirty;
uint64_t shared_clean;
@@ -41,6 +43,7 @@ struct MemUsage {
rss(0),
pss(0),
uss(0),
+ swap(0),
private_clean(0),
private_dirty(0),
shared_clean(0),
@@ -49,7 +52,7 @@ struct MemUsage {
~MemUsage() = default;
void clear() {
- vss = rss = pss = uss = 0;
+ vss = rss = pss = uss = swap = 0;
private_clean = private_dirty = shared_clean = shared_dirty = 0;
}
};
diff --git a/libmeminfo/include/meminfo/procmeminfo.h b/libmeminfo/include/meminfo/procmeminfo.h
index b37c56bcc..dd599128d 100644
--- a/libmeminfo/include/meminfo/procmeminfo.h
+++ b/libmeminfo/include/meminfo/procmeminfo.h
@@ -34,6 +34,7 @@ class ProcMemInfo final {
const std::vector<Vma>& Maps();
const MemUsage& Usage();
const MemUsage& Wss();
+ const std::vector<uint16_t>& SwapOffsets() const;
bool WssReset();
~ProcMemInfo() = default;
@@ -49,6 +50,7 @@ class ProcMemInfo final {
MemUsage usage_;
MemUsage wss_;
+ std::vector<uint16_t> swap_offsets_;
};
} // namespace meminfo
diff --git a/libmeminfo/include/meminfo/sysmeminfo.h b/libmeminfo/include/meminfo/sysmeminfo.h
index f5e05bd0e..87e14642b 100644
--- a/libmeminfo/include/meminfo/sysmeminfo.h
+++ b/libmeminfo/include/meminfo/sysmeminfo.h
@@ -28,6 +28,22 @@ namespace meminfo {
class SysMemInfo final {
// System or Global memory accounting
public:
+ static constexpr const char* kMemTotal = "MemTotal:";
+ static constexpr const char* kMemFree = "MemFree:";
+ static constexpr const char* kMemBuffers = "Buffers:";
+ static constexpr const char* kMemCached = "Cached:";
+ static constexpr const char* kMemShmem = "Shmem:";
+ static constexpr const char* kMemSlab = "Slab:";
+ static constexpr const char* kMemSReclaim = "SReclaimable:";
+ static constexpr const char* kMemSUnreclaim = "SUnreclaim:";
+ static constexpr const char* kMemSwapTotal = "SwapTotal:";
+ static constexpr const char* kMemSwapFree = "SwapFree:";
+ static constexpr const char* kMemZram = "Zram:";
+ static constexpr const char* kMemMapped = "Mapped:";
+ static constexpr const char* kMemVmallocUsed = "VmallocUsed:";
+ static constexpr const char* kMemPageTables = "PageTables:";
+ static constexpr const char* kMemKernelStack = "KernelStack:";
+
static const std::vector<std::string> kDefaultSysMemInfoTags;
SysMemInfo() = default;
@@ -38,21 +54,21 @@ class SysMemInfo final {
const std::string& path = "/proc/meminfo");
// getters
- uint64_t mem_total_kb() { return mem_in_kb_["MemTotal:"]; }
- uint64_t mem_free_kb() { return mem_in_kb_["MemFree:"]; }
- uint64_t mem_buffers_kb() { return mem_in_kb_["Buffers:"]; }
- uint64_t mem_cached_kb() { return mem_in_kb_["Cached:"]; }
- uint64_t mem_shmem_kb() { return mem_in_kb_["Shmem:"]; }
- uint64_t mem_slab_kb() { return mem_in_kb_["Slab:"]; }
- uint64_t mem_slab_reclailmable_kb() { return mem_in_kb_["SReclaimable:"]; }
- uint64_t mem_slab_unreclaimable_kb() { return mem_in_kb_["SUnreclaim:"]; }
- uint64_t mem_swap_kb() { return mem_in_kb_["SwapTotal:"]; }
- uint64_t mem_free_swap_kb() { return mem_in_kb_["SwapFree:"]; }
- uint64_t mem_zram_kb() { return mem_in_kb_["Zram:"]; }
- uint64_t mem_mapped_kb() { return mem_in_kb_["Mapped:"]; }
- uint64_t mem_vmalloc_used_kb() { return mem_in_kb_["VmallocUsed:"]; }
- uint64_t mem_page_tables_kb() { return mem_in_kb_["PageTables:"]; }
- uint64_t mem_kernel_stack_kb() { return mem_in_kb_["KernelStack:"]; }
+ uint64_t mem_total_kb() { return mem_in_kb_[kMemTotal]; }
+ uint64_t mem_free_kb() { return mem_in_kb_[kMemFree]; }
+ uint64_t mem_buffers_kb() { return mem_in_kb_[kMemBuffers]; }
+ uint64_t mem_cached_kb() { return mem_in_kb_[kMemCached]; }
+ uint64_t mem_shmem_kb() { return mem_in_kb_[kMemShmem]; }
+ uint64_t mem_slab_kb() { return mem_in_kb_[kMemSlab]; }
+ uint64_t mem_slab_reclailmable_kb() { return mem_in_kb_[kMemSReclaim]; }
+ uint64_t mem_slab_unreclaimable_kb() { return mem_in_kb_[kMemSUnreclaim]; }
+ uint64_t mem_swap_kb() { return mem_in_kb_[kMemSwapTotal]; }
+ uint64_t mem_swap_free_kb() { return mem_in_kb_[kMemSwapFree]; }
+ uint64_t mem_zram_kb() { return mem_in_kb_[kMemZram]; }
+ uint64_t mem_mapped_kb() { return mem_in_kb_[kMemMapped]; }
+ uint64_t mem_vmalloc_used_kb() { return mem_in_kb_[kMemVmallocUsed]; }
+ uint64_t mem_page_tables_kb() { return mem_in_kb_[kMemPageTables]; }
+ uint64_t mem_kernel_stack_kb() { return mem_in_kb_[kMemPageTables]; }
private:
std::map<std::string, uint64_t> mem_in_kb_;
diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp
index 7a2be4172..f973694e2 100644
--- a/libmeminfo/libmeminfo_test.cpp
+++ b/libmeminfo/libmeminfo_test.cpp
@@ -73,7 +73,7 @@ TEST_F(ValidateProcMemInfo, TestMapsEquality) {
}
}
-TEST_F(ValidateProcMemInfo, TestMapsUsage) {
+TEST_F(ValidateProcMemInfo, TestMaps) {
const std::vector<Vma>& maps = proc_mem->Maps();
ASSERT_FALSE(maps.empty());
ASSERT_EQ(proc->num_maps, maps.size());
@@ -96,6 +96,30 @@ TEST_F(ValidateProcMemInfo, TestMapsUsage) {
EXPECT_EQ(proc_usage.uss, proc_mem->Usage().uss);
}
+TEST_F(ValidateProcMemInfo, TestSwapUsage) {
+ const std::vector<Vma>& maps = proc_mem->Maps();
+ ASSERT_FALSE(maps.empty());
+ ASSERT_EQ(proc->num_maps, maps.size());
+
+ pm_memusage_t map_usage, proc_usage;
+ pm_memusage_zero(&map_usage);
+ pm_memusage_zero(&proc_usage);
+ for (size_t i = 0; i < maps.size(); i++) {
+ ASSERT_EQ(0, pm_map_usage(proc->maps[i], &map_usage));
+ EXPECT_EQ(map_usage.swap, maps[i].usage.swap) << "SWAP mismatch for map: " << maps[i].name;
+ pm_memusage_add(&proc_usage, &map_usage);
+ }
+
+ EXPECT_EQ(proc_usage.swap, proc_mem->Usage().swap);
+}
+
+TEST_F(ValidateProcMemInfo, TestSwapOffsets) {
+ const MemUsage& proc_usage = proc_mem->Usage();
+ const std::vector<uint16_t>& swap_offsets = proc_mem->SwapOffsets();
+
+ EXPECT_EQ(proc_usage.swap / getpagesize(), swap_offsets.size());
+}
+
class ValidateProcMemInfoWss : public ::testing::Test {
protected:
void SetUp() override {
diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp
index fe91d250b..e3839346a 100644
--- a/libmeminfo/procmeminfo.cpp
+++ b/libmeminfo/procmeminfo.cpp
@@ -44,6 +44,8 @@ static void add_mem_usage(MemUsage* to, const MemUsage& from) {
to->pss += from.pss;
to->uss += from.uss;
+ to->swap += from.swap;
+
to->private_clean += from.private_clean;
to->private_dirty += from.private_dirty;
@@ -76,6 +78,10 @@ const MemUsage& ProcMemInfo::Wss() {
return wss_;
}
+const std::vector<uint16_t>& ProcMemInfo::SwapOffsets() const {
+ return swap_offsets_;
+}
+
bool ProcMemInfo::WssReset() {
if (!get_wss_) {
LOG(ERROR) << "Trying to reset working set from a memory usage counting object";
@@ -115,8 +121,8 @@ bool ProcMemInfo::ReadMaps(bool get_wss) {
for (auto& vma : maps_) {
if (!ReadVmaStats(pagemap_fd.get(), vma, get_wss)) {
- LOG(ERROR) << "Failed to read page map for vma " << vma.name << "[" << vma.start
- << "-" << vma.end << "]";
+ LOG(ERROR) << "Failed to read page map for vma " << vma.name << "[" << vma.start << "-"
+ << vma.end << "]";
maps_.clear();
return false;
}
@@ -153,7 +159,8 @@ bool ProcMemInfo::ReadVmaStats(int pagemap_fd, Vma& vma, bool get_wss) {
if (!PAGE_PRESENT(p) && !PAGE_SWAPPED(p)) continue;
if (PAGE_SWAPPED(p)) {
- // TODO: do what's needed for swapped pages
+ vma.usage.swap += pagesz;
+ swap_offsets_.emplace_back(PAGE_SWAP_OFFSET(p));
continue;
}
diff --git a/libmeminfo/sysmeminfo.cpp b/libmeminfo/sysmeminfo.cpp
index 50fa2136d..82605b681 100644
--- a/libmeminfo/sysmeminfo.cpp
+++ b/libmeminfo/sysmeminfo.cpp
@@ -37,9 +37,11 @@ namespace android {
namespace meminfo {
const std::vector<std::string> SysMemInfo::kDefaultSysMemInfoTags = {
- "MemTotal:", "MemFree:", "Buffers:", "Cached:", "Shmem:",
- "Slab:", "SReclaimable:", "SUnreclaim:", "SwapTotal:", "SwapFree:",
- "ZRam:", "Mapped:", "VmallocUsed:", "PageTables:", "KernelStack:",
+ SysMemInfo::kMemTotal, SysMemInfo::kMemFree, SysMemInfo::kMemBuffers,
+ SysMemInfo::kMemCached, SysMemInfo::kMemShmem, SysMemInfo::kMemSlab,
+ SysMemInfo::kMemSReclaim, SysMemInfo::kMemSUnreclaim, SysMemInfo::kMemSwapTotal,
+ SysMemInfo::kMemSwapFree, SysMemInfo::kMemZram, SysMemInfo::kMemMapped,
+ SysMemInfo::kMemVmallocUsed, SysMemInfo::kMemPageTables, SysMemInfo::kMemKernelStack,
};
bool SysMemInfo::ReadMemInfo(const std::string& path) {
@@ -99,6 +101,7 @@ bool SysMemInfo::ReadMemInfo(const std::vector<std::string>& tags, const std::st
buffer[len] = '\0';
char* p = buffer;
uint32_t found = 0;
+ uint32_t lineno = 0;
while (*p && found < tags.size()) {
for (auto& tag : tags) {
if (strncmp(p, tag.c_str(), tag.size()) == 0) {
@@ -107,7 +110,7 @@ bool SysMemInfo::ReadMemInfo(const std::vector<std::string>& tags, const std::st
char* endptr = nullptr;
mem_in_kb_[tag] = strtoull(p, &endptr, 10);
if (p == endptr) {
- PLOG(ERROR) << "Failed to parse line in file: " << path;
+ PLOG(ERROR) << "Failed to parse line:" << lineno + 1 << " in file: " << path;
return false;
}
p = endptr;
@@ -119,6 +122,7 @@ bool SysMemInfo::ReadMemInfo(const std::vector<std::string>& tags, const std::st
p++;
}
if (*p) p++;
+ lineno++;
}
return true;