From 5a744684c3feab43f47721916d339b9111b1fd88 Mon Sep 17 00:00:00 2001 From: Erick Reyes Date: Thu, 28 Feb 2019 18:22:24 -0800 Subject: [PATCH] libmeminfo: librank optimization using maps instead of vectors librank was calling std::vector::find_if in nested loops when iterating through processes and maps. Changed the implementation to use std::map::insert, this resulted in a significant improvement to execution speed. Test: time librank on crosshatch Before: 1m22.57s real 1m15.87s user 0m05.79s system After: 0m03.85s real 0m00.88s user 0m02.92s system Bug: 124523194 Change-Id: I2b519d0bfd7f7929c6c4c6c2374794cb1a744585 Signed-off-by: Erick Reyes --- libmeminfo/tools/librank.cpp | 47 ++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/libmeminfo/tools/librank.cpp b/libmeminfo/tools/librank.cpp index 2c2583d15..e53c74610 100644 --- a/libmeminfo/tools/librank.cpp +++ b/libmeminfo/tools/librank.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -122,30 +123,22 @@ struct LibRecord { const std::string& name() const { return name_; } const MemUsage& usage() const { return usage_; } - const std::vector& processes() const { return procs_; } + const std::map& processes() const { return procs_; } uint64_t pss() const { return usage_.pss; } void AddUsage(const ProcessRecord& proc, const MemUsage& mem_usage) { - auto process = std::find_if(procs_.begin(), procs_.end(), - [&](auto p) -> bool { return p.pid() == proc.pid(); }); - if (process == procs_.end()) { - process = procs_.emplace(procs_.end(), proc.pid()); - } - process->AddUsage(mem_usage); + auto [it, inserted] = procs_.insert(std::pair(proc.pid(), proc)); + it->second.AddUsage(mem_usage); add_mem_usage(&usage_, mem_usage); } - void Sort(std::function& sorter) { - std::sort(procs_.begin(), procs_.end(), sorter); - } - private: std::string name_; MemUsage usage_; - std::vector procs_; + std::map procs_; }; // List of every library / map -static std::vector g_libs; +static std::map g_libs; // List of library/map names that we don't want to show by default static const std::vector g_blacklisted_libs = {"[heap]", "[stack]"}; @@ -204,13 +197,10 @@ static bool scan_libs_per_process(pid_t pid) { continue; } - auto lib = std::find_if(g_libs.begin(), g_libs.end(), - [&](auto l) -> bool { return map.name == l.name(); }); - if (lib == g_libs.end()) { - lib = g_libs.emplace(g_libs.end(), map.name); - } + auto [it, inserted] = + g_libs.insert(std::pair(map.name, LibRecord(map.name))); + it->second.AddUsage(proc, map.usage); - lib->AddUsage(proc, map.usage); if (!g_has_swap && map.usage.swap) { g_has_swap = true; } @@ -321,11 +311,16 @@ int main(int argc, char* argv[]) { } printf("Name/PID\n"); + std::vector v_libs; + v_libs.reserve(g_libs.size()); + std::transform(g_libs.begin(), g_libs.end(), std::back_inserter(v_libs), + [] (std::pair const& pair) { return pair.second; }); + // sort the libraries by their pss - std::sort(g_libs.begin(), g_libs.end(), + std::sort(v_libs.begin(), v_libs.end(), [](const LibRecord& l1, const LibRecord& l2) { return l1.pss() > l2.pss(); }); - for (auto& lib : g_libs) { + for (auto& lib : v_libs) { printf("%6" PRIu64 "K %7s %6s %6s %6s ", lib.pss() / 1024, "", "", "", ""); if (g_has_swap) { printf(" %6s ", ""); @@ -333,9 +328,15 @@ int main(int argc, char* argv[]) { printf("%s\n", lib.name().c_str()); // sort all mappings first - lib.Sort(sort_func); - for (auto& p : lib.processes()) { + std::vector procs; + procs.reserve(lib.processes().size()); + std::transform(lib.processes().begin(), lib.processes().end(), std::back_inserter(procs), + [] (std::pair const& pair) { return pair.second; }); + + std::sort(procs.begin(), procs.end(), sort_func); + + for (auto& p : procs) { const MemUsage& usage = p.usage(); printf(" %6s %7" PRIu64 "K %6" PRIu64 "K %6" PRIu64 "K %6" PRIu64 "K ", "", usage.vss / 1024, usage.rss / 1024, usage.pss / 1024, usage.uss / 1024);