JDevlieghere created this revision.
JDevlieghere added reviewers: clayborg, labath.
JDevlieghere requested review of this revision.

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.


https://reviews.llvm.org/D117914

Files:
  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

Index: lldb/test/API/commands/statistics/basic/TestStats.py
===================================================================
--- lldb/test/API/commands/statistics/basic/TestStats.py
+++ lldb/test/API/commands/statistics/basic/TestStats.py
@@ -135,6 +135,7 @@
 
         (lldb) statistics dump
         {
+          "strings" : {...},
           "modules" : [...],
           "targets" : [
             {
@@ -160,6 +161,7 @@
         target = self.createTestTarget()
         debug_stats = self.get_stats()
         debug_stat_keys = [
+            'strings',
             'modules',
             'targets',
             'totalSymbolTableParseTime',
@@ -197,6 +199,7 @@
 
         (lldb) statistics dump
         {
+          "strings" : {...},
           "modules" : [...],
           "targets" : [
                 {
@@ -227,6 +230,7 @@
                                           lldb.SBFileSpec("main.c"))
         debug_stats = self.get_stats()
         debug_stat_keys = [
+            'strings',
             'modules',
             'targets',
             'totalSymbolTableParseTime',
@@ -254,6 +258,36 @@
         self.assertGreater(stats['launchOrAttachTime'], 0.0)
         self.assertGreater(stats['targetCreateTime'], 0.0)
 
+    def test_strings(self):
+        """
+            Test "statistics dump" and the string memory information.
+        """
+        exe = self.getBuildArtifact("a.out")
+        target = self.createTestTarget(file_path=exe)
+        debug_stats = self.get_stats()
+        debug_stat_keys = [
+            'strings',
+            'modules',
+            'targets',
+            'totalSymbolTableParseTime',
+            'totalSymbolTableIndexTime',
+            'totalSymbolTablesLoadedFromCache',
+            'totalSymbolTablesSavedToCache',
+            'totalDebugInfoParseTime',
+            'totalDebugInfoIndexTime',
+            'totalDebugInfoIndexLoadedFromCache',
+            'totalDebugInfoIndexSavedToCache',
+            'totalDebugInfoByteSize'
+        ]
+        self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None)
+        stats = debug_stats['strings']
+        keys_exist = [
+            'bytesTotal',
+            'bytesAllocated',
+            'bytesWasted',
+        ]
+        self.verify_keys(stats, '"stats"', keys_exist, None)
+
     def find_module_in_metrics(self, path, stats):
         modules = stats['modules']
         for module in modules:
@@ -269,6 +303,7 @@
         target = self.createTestTarget(file_path=exe)
         debug_stats = self.get_stats()
         debug_stat_keys = [
+            'strings',
             'modules',
             'targets',
             'totalSymbolTableParseTime',
@@ -312,6 +347,7 @@
         Output expected to be something like:
 
         {
+          "strings" : {...},
           "modules" : [...],
           "targets" : [
                 {
@@ -355,6 +391,7 @@
         self.runCmd("b a_function")
         debug_stats = self.get_stats()
         debug_stat_keys = [
+            'strings',
             'modules',
             'targets',
             'totalSymbolTableParseTime',
Index: lldb/source/Utility/ConstString.cpp
===================================================================
--- lldb/source/Utility/ConstString.cpp
+++ lldb/source/Utility/ConstString.cpp
@@ -171,6 +171,17 @@
     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.total_memory += alloc.getTotalMemory();
+      stats.bytes_allocated += alloc.getBytesAllocated();
+    }
+    return stats;
+  }
+
 protected:
   uint8_t hash(const llvm::StringRef &s) const {
     uint32_t h = llvm::djbHash(s);
@@ -332,6 +343,10 @@
   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) {
Index: lldb/source/Target/Statistics.cpp
===================================================================
--- lldb/source/Target/Statistics.cpp
+++ lldb/source/Target/Statistics.cpp
@@ -65,6 +65,14 @@
   return module;
 }
 
+llvm::json::Value StringStats::ToJSON() const {
+  json::Object obj;
+  obj.try_emplace<int64_t>("bytesTotal", stats.GetTotalMemory());
+  obj.try_emplace<int64_t>("bytesAllocated", stats.GetBytesAllocated());
+  obj.try_emplace<int64_t>("bytesWasted", stats.GetBytesWasted());
+  return obj;
+}
+
 json::Value TargetStats::ToJSON(Target &target) {
   CollectStats(target);
 
@@ -212,9 +220,12 @@
     json_modules.emplace_back(module_stat.ToJSON());
   }
 
+  StringStats string_stats;
+
   json::Object global_stats{
       {"targets", std::move(json_targets)},
       {"modules", std::move(json_modules)},
+      {"strings", string_stats.ToJSON()},
       {"totalSymbolTableParseTime", symtab_parse_time},
       {"totalSymbolTableIndexTime", symtab_index_time},
       {"totalSymbolTablesLoadedFromCache", symtabs_loaded},
Index: lldb/include/lldb/Utility/ConstString.h
===================================================================
--- lldb/include/lldb/Utility/ConstString.h
+++ lldb/include/lldb/Utility/ConstString.h
@@ -408,6 +408,16 @@
   ///     in memory.
   static size_t StaticMemorySize();
 
+  struct MemoryStats {
+    size_t GetTotalMemory() const { return total_memory; }
+    size_t GetBytesAllocated() const { return bytes_allocated; }
+    size_t GetBytesWasted() const { return total_memory - bytes_allocated; }
+    size_t total_memory;
+    size_t bytes_allocated;
+  };
+
+  static MemoryStats GetMemoryStats();
+
 protected:
   template <typename T, typename Enable> friend struct ::llvm::DenseMapInfo;
   /// Only used by DenseMapInfo.
Index: lldb/include/lldb/Target/Statistics.h
===================================================================
--- lldb/include/lldb/Target/Statistics.h
+++ 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 @@
   bool debug_info_index_saved_to_cache = false;
 };
 
+struct StringStats {
+  llvm::json::Value ToJSON() const;
+  ConstString::MemoryStats stats = ConstString::GetMemoryStats();
+};
+
 /// A class that represents statistics for a since lldb_private::Target.
 class TargetStats {
 public:
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to