Author: Jonas Devlieghere Date: 2022-01-24T15:13:17-08:00 New Revision: cd8122b27f8fb9cbf222ef946bff3b698625e2f4
URL: https://github.com/llvm/llvm-project/commit/cd8122b27f8fb9cbf222ef946bff3b698625e2f4 DIFF: https://github.com/llvm/llvm-project/commit/cd8122b27f8fb9cbf222ef946bff3b698625e2f4.diff LOG: [lldb] Add ConstString memory usage statistics Add statistics about the memory usage of the string pool. I'm particularly interested in the memory used by the allocator, i.e. the number of bytes actually used by the allocator it self as well as the number of bytes allocated through the allocator. Differential revision: https://reviews.llvm.org/D117914 Added: Modified: lldb/include/lldb/Target/Statistics.h lldb/include/lldb/Utility/ConstString.h lldb/source/Target/Statistics.cpp lldb/source/Utility/ConstString.cpp lldb/test/API/commands/statistics/basic/TestStats.py Removed: ################################################################################ diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h index 185389b2eeafe..d2b8f746a38c8 100644 --- a/lldb/include/lldb/Target/Statistics.h +++ b/lldb/include/lldb/Target/Statistics.h @@ -9,6 +9,7 @@ #ifndef LLDB_TARGET_STATISTICS_H #define LLDB_TARGET_STATISTICS_H +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/Stream.h" #include "lldb/lldb-forward.h" #include "llvm/Support/JSON.h" @@ -110,6 +111,11 @@ struct ModuleStats { bool debug_info_index_saved_to_cache = false; }; +struct ConstStringStats { + llvm::json::Value ToJSON() const; + ConstString::MemoryStats stats = ConstString::GetMemoryStats(); +}; + /// A class that represents statistics for a since lldb_private::Target. class TargetStats { public: diff --git a/lldb/include/lldb/Utility/ConstString.h b/lldb/include/lldb/Utility/ConstString.h index 2756f1fd72038..937f8271a9a8e 100644 --- a/lldb/include/lldb/Utility/ConstString.h +++ b/lldb/include/lldb/Utility/ConstString.h @@ -408,6 +408,16 @@ class ConstString { /// in memory. static size_t StaticMemorySize(); + struct MemoryStats { + size_t GetBytesTotal() const { return bytes_total; } + size_t GetBytesUsed() const { return bytes_used; } + size_t GetBytesUnused() const { return bytes_total - bytes_used; } + size_t bytes_total = 0; + size_t bytes_used = 0; + }; + + static MemoryStats GetMemoryStats(); + protected: template <typename T, typename Enable> friend struct ::llvm::DenseMapInfo; /// Only used by DenseMapInfo. diff --git a/lldb/source/Target/Statistics.cpp b/lldb/source/Target/Statistics.cpp index 8d1e982c3b988..ebddad837d14b 100644 --- a/lldb/source/Target/Statistics.cpp +++ b/lldb/source/Target/Statistics.cpp @@ -65,6 +65,14 @@ json::Value ModuleStats::ToJSON() const { return module; } +llvm::json::Value ConstStringStats::ToJSON() const { + json::Object obj; + obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal()); + obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed()); + obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused()); + return obj; +} + json::Value TargetStats::ToJSON(Target &target) { CollectStats(target); @@ -212,9 +220,15 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger, json_modules.emplace_back(module_stat.ToJSON()); } + ConstStringStats const_string_stats; + json::Object json_memory{ + {"strings", const_string_stats.ToJSON()}, + }; + json::Object global_stats{ {"targets", std::move(json_targets)}, {"modules", std::move(json_modules)}, + {"memory", std::move(json_memory)}, {"totalSymbolTableParseTime", symtab_parse_time}, {"totalSymbolTableIndexTime", symtab_index_time}, {"totalSymbolTablesLoadedFromCache", symtabs_loaded}, diff --git a/lldb/source/Utility/ConstString.cpp b/lldb/source/Utility/ConstString.cpp index e5e1b2387e64d..76270e3f53b96 100644 --- a/lldb/source/Utility/ConstString.cpp +++ b/lldb/source/Utility/ConstString.cpp @@ -171,6 +171,17 @@ class Pool { return mem_size; } + ConstString::MemoryStats GetMemoryStats() const { + ConstString::MemoryStats stats; + for (const auto &pool : m_string_pools) { + llvm::sys::SmartScopedReader<false> rlock(pool.m_mutex); + const Allocator &alloc = pool.m_string_map.getAllocator(); + stats.bytes_total += alloc.getTotalMemory(); + stats.bytes_used += alloc.getBytesAllocated(); + } + return stats; + } + protected: uint8_t hash(const llvm::StringRef &s) const { uint32_t h = llvm::djbHash(s); @@ -332,6 +343,10 @@ size_t ConstString::StaticMemorySize() { return StringPool().MemorySize(); } +ConstString::MemoryStats ConstString::GetMemoryStats() { + return StringPool().GetMemoryStats(); +} + void llvm::format_provider<ConstString>::format(const ConstString &CS, llvm::raw_ostream &OS, llvm::StringRef Options) { diff --git a/lldb/test/API/commands/statistics/basic/TestStats.py b/lldb/test/API/commands/statistics/basic/TestStats.py index f69fddc27fbaa..99940ed5061f9 100644 --- a/lldb/test/API/commands/statistics/basic/TestStats.py +++ b/lldb/test/API/commands/statistics/basic/TestStats.py @@ -135,6 +135,7 @@ def test_default_no_run(self): (lldb) statistics dump { + "memory" : {...}, "modules" : [...], "targets" : [ { @@ -160,6 +161,7 @@ def test_default_no_run(self): target = self.createTestTarget() debug_stats = self.get_stats() debug_stat_keys = [ + 'memory', 'modules', 'targets', 'totalSymbolTableParseTime', @@ -197,6 +199,7 @@ def test_default_with_run(self): (lldb) statistics dump { + "memory" : {...}, "modules" : [...], "targets" : [ { @@ -227,6 +230,7 @@ def test_default_with_run(self): lldb.SBFileSpec("main.c")) debug_stats = self.get_stats() debug_stat_keys = [ + 'memory', 'modules', 'targets', 'totalSymbolTableParseTime', @@ -254,6 +258,44 @@ def test_default_with_run(self): self.assertGreater(stats['launchOrAttachTime'], 0.0) self.assertGreater(stats['targetCreateTime'], 0.0) + def test_memory(self): + """ + Test "statistics dump" and the memory information. + """ + exe = self.getBuildArtifact("a.out") + target = self.createTestTarget(file_path=exe) + debug_stats = self.get_stats() + debug_stat_keys = [ + 'memory', + 'modules', + 'targets', + 'totalSymbolTableParseTime', + 'totalSymbolTableIndexTime', + 'totalSymbolTablesLoadedFromCache', + 'totalSymbolTablesSavedToCache', + 'totalDebugInfoParseTime', + 'totalDebugInfoIndexTime', + 'totalDebugInfoIndexLoadedFromCache', + 'totalDebugInfoIndexSavedToCache', + 'totalDebugInfoByteSize' + ] + self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None) + + memory = debug_stats['memory'] + memory_keys= [ + 'strings', + ] + self.verify_keys(memory, '"memory"', memory_keys, None) + + strings = memory['strings'] + strings_keys= [ + 'bytesTotal', + 'bytesUsed', + 'bytesUnused', + ] + self.verify_keys(strings, '"strings"', strings_keys, None) + + def find_module_in_metrics(self, path, stats): modules = stats['modules'] for module in modules: @@ -269,6 +311,7 @@ def test_modules(self): target = self.createTestTarget(file_path=exe) debug_stats = self.get_stats() debug_stat_keys = [ + 'memory', 'modules', 'targets', 'totalSymbolTableParseTime', @@ -312,6 +355,7 @@ def test_breakpoints(self): Output expected to be something like: { + "memory" : {...}, "modules" : [...], "targets" : [ { @@ -355,6 +399,7 @@ def test_breakpoints(self): self.runCmd("b a_function") debug_stats = self.get_stats() debug_stat_keys = [ + 'memory', 'modules', 'targets', 'totalSymbolTableParseTime', _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits