Loading libmeminfo/Android.bp +9 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,11 @@ cc_test { srcs: [ "libmeminfo_test.cpp" ], data: [ "testdata1/*", "testdata2/*" ], } cc_benchmark { Loading @@ -67,4 +72,8 @@ cc_benchmark { "libmeminfo", "libprocinfo", ], data: [ "testdata1/*", ], } libmeminfo/include/meminfo/meminfo.h +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -41,6 +43,7 @@ struct MemUsage { rss(0), pss(0), uss(0), swap(0), private_clean(0), private_dirty(0), shared_clean(0), Loading @@ -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; } }; Loading libmeminfo/include/meminfo/procmeminfo.h +8 −2 Original line number Diff line number Diff line Loading @@ -29,13 +29,16 @@ namespace meminfo { class ProcMemInfo final { // Per-process memory accounting public: ProcMemInfo(pid_t pid, bool get_wss = false); // Reset the working set accounting of the process via /proc/<pid>/clear_refs static bool ResetWorkingSet(pid_t pid); ProcMemInfo(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0); const std::vector<Vma>& Maps(); const MemUsage& Usage(); const MemUsage& Wss(); const std::vector<uint16_t>& SwapOffsets(); bool WssReset(); ~ProcMemInfo() = default; private: Loading @@ -44,11 +47,14 @@ class ProcMemInfo final { pid_t pid_; bool get_wss_; uint64_t pgflags_; uint64_t pgflags_mask_; std::vector<Vma> maps_; MemUsage usage_; MemUsage wss_; std::vector<uint16_t> swap_offsets_; }; } // namespace meminfo Loading libmeminfo/include/meminfo/sysmeminfo.h +31 −15 Original line number Diff line number Diff line Loading @@ -28,6 +28,21 @@ 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* 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; Loading @@ -38,24 +53,25 @@ 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_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]; } uint64_t mem_zram_kb(const std::string& zram_dev = ""); private: std::map<std::string, uint64_t> mem_in_kb_; bool MemZramDevice(const std::string& zram_dev, uint64_t* mem_zram_dev); }; } // namespace meminfo Loading libmeminfo/libmeminfo_benchmark.cpp +56 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #include <meminfo/sysmeminfo.h> #include <fcntl.h> #include <inttypes.h> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> Loading Loading @@ -46,7 +48,7 @@ enum { MEMINFO_COUNT }; void get_mem_info(uint64_t mem[], const char* file) { static void get_mem_info(uint64_t mem[], const char* file) { char buffer[4096]; unsigned int numFound = 0; Loading @@ -69,7 +71,8 @@ void get_mem_info(uint64_t mem[], const char* file) { static const char* const tags[] = { "MemTotal:", "MemFree:", "Buffers:", "Cached:", "Shmem:", "Slab:", "SReclaimable:", "SUnreclaim:", "SwapTotal:", "SwapFree:", "ZRam:", "Mapped:", "VmallocUsed:", "PageTables:", "KernelStack:", NULL}; "VmallocUsed:", "PageTables:", "KernelStack:", NULL }; static const int tagsLen[] = {9, 8, 8, 7, 6, 5, 13, 11, 10, 9, 5, 7, 12, 11, 12, 0}; Loading @@ -78,7 +81,8 @@ void get_mem_info(uint64_t mem[], const char* file) { while (*p && (numFound < (sizeof(tagsLen) / sizeof(tagsLen[0])))) { int i = 0; while (tags[i]) { //std::cout << "tag =" << tags[i] << " p = " << std::string(p, tagsLen[i]) << std::endl; // std::cout << "tag =" << tags[i] << " p = " << std::string(p, tagsLen[i]) << // std::endl; if (strncmp(p, tags[i], tagsLen[i]) == 0) { p += tagsLen[i]; while (*p == ' ') p++; Loading Loading @@ -214,4 +218,51 @@ Hugepagesize: 2048 kB)meminfo"; } BENCHMARK(BM_ReadMemInfo); static uint64_t get_zram_mem_used(const std::string& zram_dir) { FILE* f = fopen((zram_dir + "mm_stat").c_str(), "r"); if (f) { uint64_t mem_used_total = 0; int matched = fscanf(f, "%*d %*d %" SCNu64 " %*d %*d %*d %*d", &mem_used_total); if (matched != 1) fprintf(stderr, "warning: failed to parse %s\n", (zram_dir + "mm_stat").c_str()); fclose(f); return mem_used_total; } f = fopen((zram_dir + "mem_used_total").c_str(), "r"); if (f) { uint64_t mem_used_total = 0; int matched = fscanf(f, "%" SCNu64, &mem_used_total); if (matched != 1) fprintf(stderr, "warning: failed to parse %s\n", (zram_dir + "mem_used_total").c_str()); fclose(f); return mem_used_total; } return 0; } static void BM_OldReadZramTotal(benchmark::State& state) { std::string exec_dir = ::android::base::GetExecutableDirectory(); std::string zram_mmstat_dir = exec_dir + "/testdata1/"; for (auto _ : state) { uint64_t zram_total __attribute__((unused)) = get_zram_mem_used(zram_mmstat_dir) / 1024; } } BENCHMARK(BM_OldReadZramTotal); static void BM_NewReadZramTotal(benchmark::State& state) { std::string exec_dir = ::android::base::GetExecutableDirectory(); std::string zram_mmstat_dir = exec_dir + "/testdata1/"; ::android::meminfo::SysMemInfo mi; for (auto _ : state) { uint64_t zram_total __attribute__((unused)) = mi.mem_zram_kb(zram_mmstat_dir); } } BENCHMARK(BM_NewReadZramTotal); BENCHMARK_MAIN(); Loading
libmeminfo/Android.bp +9 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,11 @@ cc_test { srcs: [ "libmeminfo_test.cpp" ], data: [ "testdata1/*", "testdata2/*" ], } cc_benchmark { Loading @@ -67,4 +72,8 @@ cc_benchmark { "libmeminfo", "libprocinfo", ], data: [ "testdata1/*", ], }
libmeminfo/include/meminfo/meminfo.h +4 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -41,6 +43,7 @@ struct MemUsage { rss(0), pss(0), uss(0), swap(0), private_clean(0), private_dirty(0), shared_clean(0), Loading @@ -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; } }; Loading
libmeminfo/include/meminfo/procmeminfo.h +8 −2 Original line number Diff line number Diff line Loading @@ -29,13 +29,16 @@ namespace meminfo { class ProcMemInfo final { // Per-process memory accounting public: ProcMemInfo(pid_t pid, bool get_wss = false); // Reset the working set accounting of the process via /proc/<pid>/clear_refs static bool ResetWorkingSet(pid_t pid); ProcMemInfo(pid_t pid, bool get_wss = false, uint64_t pgflags = 0, uint64_t pgflags_mask = 0); const std::vector<Vma>& Maps(); const MemUsage& Usage(); const MemUsage& Wss(); const std::vector<uint16_t>& SwapOffsets(); bool WssReset(); ~ProcMemInfo() = default; private: Loading @@ -44,11 +47,14 @@ class ProcMemInfo final { pid_t pid_; bool get_wss_; uint64_t pgflags_; uint64_t pgflags_mask_; std::vector<Vma> maps_; MemUsage usage_; MemUsage wss_; std::vector<uint16_t> swap_offsets_; }; } // namespace meminfo Loading
libmeminfo/include/meminfo/sysmeminfo.h +31 −15 Original line number Diff line number Diff line Loading @@ -28,6 +28,21 @@ 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* 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; Loading @@ -38,24 +53,25 @@ 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_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]; } uint64_t mem_zram_kb(const std::string& zram_dev = ""); private: std::map<std::string, uint64_t> mem_in_kb_; bool MemZramDevice(const std::string& zram_dev, uint64_t* mem_zram_dev); }; } // namespace meminfo Loading
libmeminfo/libmeminfo_benchmark.cpp +56 −5 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ #include <meminfo/sysmeminfo.h> #include <fcntl.h> #include <inttypes.h> #include <stdio.h> #include <sys/stat.h> #include <sys/types.h> Loading Loading @@ -46,7 +48,7 @@ enum { MEMINFO_COUNT }; void get_mem_info(uint64_t mem[], const char* file) { static void get_mem_info(uint64_t mem[], const char* file) { char buffer[4096]; unsigned int numFound = 0; Loading @@ -69,7 +71,8 @@ void get_mem_info(uint64_t mem[], const char* file) { static const char* const tags[] = { "MemTotal:", "MemFree:", "Buffers:", "Cached:", "Shmem:", "Slab:", "SReclaimable:", "SUnreclaim:", "SwapTotal:", "SwapFree:", "ZRam:", "Mapped:", "VmallocUsed:", "PageTables:", "KernelStack:", NULL}; "VmallocUsed:", "PageTables:", "KernelStack:", NULL }; static const int tagsLen[] = {9, 8, 8, 7, 6, 5, 13, 11, 10, 9, 5, 7, 12, 11, 12, 0}; Loading @@ -78,7 +81,8 @@ void get_mem_info(uint64_t mem[], const char* file) { while (*p && (numFound < (sizeof(tagsLen) / sizeof(tagsLen[0])))) { int i = 0; while (tags[i]) { //std::cout << "tag =" << tags[i] << " p = " << std::string(p, tagsLen[i]) << std::endl; // std::cout << "tag =" << tags[i] << " p = " << std::string(p, tagsLen[i]) << // std::endl; if (strncmp(p, tags[i], tagsLen[i]) == 0) { p += tagsLen[i]; while (*p == ' ') p++; Loading Loading @@ -214,4 +218,51 @@ Hugepagesize: 2048 kB)meminfo"; } BENCHMARK(BM_ReadMemInfo); static uint64_t get_zram_mem_used(const std::string& zram_dir) { FILE* f = fopen((zram_dir + "mm_stat").c_str(), "r"); if (f) { uint64_t mem_used_total = 0; int matched = fscanf(f, "%*d %*d %" SCNu64 " %*d %*d %*d %*d", &mem_used_total); if (matched != 1) fprintf(stderr, "warning: failed to parse %s\n", (zram_dir + "mm_stat").c_str()); fclose(f); return mem_used_total; } f = fopen((zram_dir + "mem_used_total").c_str(), "r"); if (f) { uint64_t mem_used_total = 0; int matched = fscanf(f, "%" SCNu64, &mem_used_total); if (matched != 1) fprintf(stderr, "warning: failed to parse %s\n", (zram_dir + "mem_used_total").c_str()); fclose(f); return mem_used_total; } return 0; } static void BM_OldReadZramTotal(benchmark::State& state) { std::string exec_dir = ::android::base::GetExecutableDirectory(); std::string zram_mmstat_dir = exec_dir + "/testdata1/"; for (auto _ : state) { uint64_t zram_total __attribute__((unused)) = get_zram_mem_used(zram_mmstat_dir) / 1024; } } BENCHMARK(BM_OldReadZramTotal); static void BM_NewReadZramTotal(benchmark::State& state) { std::string exec_dir = ::android::base::GetExecutableDirectory(); std::string zram_mmstat_dir = exec_dir + "/testdata1/"; ::android::meminfo::SysMemInfo mi; for (auto _ : state) { uint64_t zram_total __attribute__((unused)) = mi.mem_zram_kb(zram_mmstat_dir); } } BENCHMARK(BM_NewReadZramTotal); BENCHMARK_MAIN();