From 8871e7e90f393bce69608ea19112aa15e4914166 Mon Sep 17 00:00:00 2001 From: Sandeep Patil Date: Sun, 13 Jan 2019 16:47:20 -0800 Subject: [PATCH] meminfo: Add SmapsOrRollupPss Adds SmapsOrRollup parsing methods to only read Pss of the process fomr /proc//{smaps, smaps_rollup}. Bug: 111694435 Test: libmeminfo_test 1 --gtest_filter=TestProcMemInfo.* Change-Id: I31b982ae5ff2bb5b165ea33f6c57755ee34cbbc7 Merged-In: I31b982ae5ff2bb5b165ea33f6c57755ee34cbbc7 Signed-off-by: Sandeep Patil --- libmeminfo/include/meminfo/procmeminfo.h | 10 ++++++ libmeminfo/libmeminfo_test.cpp | 44 ++++++++++++++++++++++++ libmeminfo/procmeminfo.cpp | 23 +++++++++++++ 3 files changed, 77 insertions(+) diff --git a/libmeminfo/include/meminfo/procmeminfo.h b/libmeminfo/include/meminfo/procmeminfo.h index c5f8c3c11..4cce133ae 100644 --- a/libmeminfo/include/meminfo/procmeminfo.h +++ b/libmeminfo/include/meminfo/procmeminfo.h @@ -66,6 +66,11 @@ class ProcMemInfo final { // All other fields of MemUsage are zeroed. bool SmapsOrRollup(bool use_rollup, MemUsage* stats) const; + // Used to parse either of /proc//{smaps, smaps_rollup} and record the process's + // Pss. The 'use_rollup' parameter decides which file is to be tried. + // Returns 'true' on success and the value of Pss in the out parameter. + bool SmapsOrRollupPss(bool use_rollup, uint64_t* pss) const; + const std::vector& SwapOffsets(); ~ProcMemInfo() = default; @@ -94,5 +99,10 @@ bool ForEachVmaFromFile(const std::string& path, const VmaCallback& callback); // or /proc//smaps_rollup bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats); +// Same as ProcMemInfo::SmapsOrRollupPss but reads the statistics directly +// from a file and returns total Pss in kB. The file MUST be in the same format +// as /proc//smaps or /proc//smaps_rollup +bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss); + } // namespace meminfo } // namespace android diff --git a/libmeminfo/libmeminfo_test.cpp b/libmeminfo/libmeminfo_test.cpp index 2529bd76c..796a7d0fe 100644 --- a/libmeminfo/libmeminfo_test.cpp +++ b/libmeminfo/libmeminfo_test.cpp @@ -365,6 +365,50 @@ VmFlags: rd wr mr mw me ac EXPECT_EQ(stats.swap_pss, 70); } +TEST(TestProcMemInfo, SmapsOrRollupPssRollupTest) { + // This is a made up smaps for the test + std::string smaps = + R"smaps(12c00000-13440000 rw-p 00000000 00:00 0 [anon:dalvik-main space (region space)] +Name: [anon:dalvik-main space (region space)] +Size: 8448 kB +KernelPageSize: 4 kB +MMUPageSize: 4 kB +Rss: 2652 kB +Pss: 2652 kB +Shared_Clean: 840 kB +Shared_Dirty: 40 kB +Private_Clean: 84 kB +Private_Dirty: 2652 kB +Referenced: 2652 kB +Anonymous: 2652 kB +AnonHugePages: 0 kB +ShmemPmdMapped: 0 kB +Shared_Hugetlb: 0 kB +Private_Hugetlb: 0 kB +Swap: 102 kB +SwapPss: 70 kB +Locked: 2652 kB +VmFlags: rd wr mr mw me ac +)smaps"; + + TemporaryFile tf; + ASSERT_TRUE(tf.fd != -1); + ASSERT_TRUE(::android::base::WriteStringToFd(smaps, tf.fd)); + + uint64_t pss; + ASSERT_EQ(SmapsOrRollupPssFromFile(tf.path, &pss), true); + EXPECT_EQ(pss, 2652); +} + +TEST(TestProcMemInfo, SmapsOrRollupPssSmapsTest) { + std::string exec_dir = ::android::base::GetExecutableDirectory(); + std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str()); + + uint64_t pss; + ASSERT_EQ(SmapsOrRollupPssFromFile(path, &pss), true); + EXPECT_EQ(pss, 19119); +} + TEST(TestProcMemInfo, ForEachVmaFromFileTest) { std::string exec_dir = ::android::base::GetExecutableDirectory(); std::string path = ::android::base::StringPrintf("%s/testdata1/smaps_short", exec_dir.c_str()); diff --git a/libmeminfo/procmeminfo.cpp b/libmeminfo/procmeminfo.cpp index 9345bda90..f72d46964 100644 --- a/libmeminfo/procmeminfo.cpp +++ b/libmeminfo/procmeminfo.cpp @@ -178,6 +178,12 @@ bool ProcMemInfo::SmapsOrRollup(bool use_rollup, MemUsage* stats) const { return SmapsOrRollupFromFile(path, stats); }; +bool ProcMemInfo::SmapsOrRollupPss(bool use_rollup, uint64_t* pss) const { + std::string path = ::android::base::StringPrintf("/proc/%d/%s", pid_, + use_rollup ? "smaps_rollup" : "smaps"); + return SmapsOrRollupPssFromFile(path, pss); +} + const std::vector& ProcMemInfo::SwapOffsets() { if (get_wss_) { LOG(WARNING) << "Trying to read process swap offsets for " << pid_ @@ -412,5 +418,22 @@ bool SmapsOrRollupFromFile(const std::string& path, MemUsage* stats) { return true; } +bool SmapsOrRollupPssFromFile(const std::string& path, uint64_t* pss) { + auto fp = std::unique_ptr{fopen(path.c_str(), "re"), fclose}; + if (fp == nullptr) { + return false; + } + *pss = 0; + char line[1024]; + while (fgets(line, sizeof(line), fp.get()) != nullptr) { + uint64_t v; + if (sscanf(line, "Pss: %" SCNu64 " kB", &v) == 1) { + *pss += v; + } + } + + return true; +} + } // namespace meminfo } // namespace android