Skip to content

Commit cd8122b

Browse files
committed
[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
1 parent 9407a70 commit cd8122b

File tree

5 files changed

+90
-0
lines changed

5 files changed

+90
-0
lines changed

lldb/include/lldb/Target/Statistics.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLDB_TARGET_STATISTICS_H
1010
#define LLDB_TARGET_STATISTICS_H
1111

12+
#include "lldb/Utility/ConstString.h"
1213
#include "lldb/Utility/Stream.h"
1314
#include "lldb/lldb-forward.h"
1415
#include "llvm/Support/JSON.h"
@@ -110,6 +111,11 @@ struct ModuleStats {
110111
bool debug_info_index_saved_to_cache = false;
111112
};
112113

114+
struct ConstStringStats {
115+
llvm::json::Value ToJSON() const;
116+
ConstString::MemoryStats stats = ConstString::GetMemoryStats();
117+
};
118+
113119
/// A class that represents statistics for a since lldb_private::Target.
114120
class TargetStats {
115121
public:

lldb/include/lldb/Utility/ConstString.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,16 @@ class ConstString {
408408
/// in memory.
409409
static size_t StaticMemorySize();
410410

411+
struct MemoryStats {
412+
size_t GetBytesTotal() const { return bytes_total; }
413+
size_t GetBytesUsed() const { return bytes_used; }
414+
size_t GetBytesUnused() const { return bytes_total - bytes_used; }
415+
size_t bytes_total = 0;
416+
size_t bytes_used = 0;
417+
};
418+
419+
static MemoryStats GetMemoryStats();
420+
411421
protected:
412422
template <typename T, typename Enable> friend struct ::llvm::DenseMapInfo;
413423
/// Only used by DenseMapInfo.

lldb/source/Target/Statistics.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ json::Value ModuleStats::ToJSON() const {
6565
return module;
6666
}
6767

68+
llvm::json::Value ConstStringStats::ToJSON() const {
69+
json::Object obj;
70+
obj.try_emplace<int64_t>("bytesTotal", stats.GetBytesTotal());
71+
obj.try_emplace<int64_t>("bytesUsed", stats.GetBytesUsed());
72+
obj.try_emplace<int64_t>("bytesUnused", stats.GetBytesUnused());
73+
return obj;
74+
}
75+
6876
json::Value TargetStats::ToJSON(Target &target) {
6977
CollectStats(target);
7078

@@ -212,9 +220,15 @@ llvm::json::Value DebuggerStats::ReportStatistics(Debugger &debugger,
212220
json_modules.emplace_back(module_stat.ToJSON());
213221
}
214222

223+
ConstStringStats const_string_stats;
224+
json::Object json_memory{
225+
{"strings", const_string_stats.ToJSON()},
226+
};
227+
215228
json::Object global_stats{
216229
{"targets", std::move(json_targets)},
217230
{"modules", std::move(json_modules)},
231+
{"memory", std::move(json_memory)},
218232
{"totalSymbolTableParseTime", symtab_parse_time},
219233
{"totalSymbolTableIndexTime", symtab_index_time},
220234
{"totalSymbolTablesLoadedFromCache", symtabs_loaded},

lldb/source/Utility/ConstString.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,17 @@ class Pool {
171171
return mem_size;
172172
}
173173

174+
ConstString::MemoryStats GetMemoryStats() const {
175+
ConstString::MemoryStats stats;
176+
for (const auto &pool : m_string_pools) {
177+
llvm::sys::SmartScopedReader<false> rlock(pool.m_mutex);
178+
const Allocator &alloc = pool.m_string_map.getAllocator();
179+
stats.bytes_total += alloc.getTotalMemory();
180+
stats.bytes_used += alloc.getBytesAllocated();
181+
}
182+
return stats;
183+
}
184+
174185
protected:
175186
uint8_t hash(const llvm::StringRef &s) const {
176187
uint32_t h = llvm::djbHash(s);
@@ -332,6 +343,10 @@ size_t ConstString::StaticMemorySize() {
332343
return StringPool().MemorySize();
333344
}
334345

346+
ConstString::MemoryStats ConstString::GetMemoryStats() {
347+
return StringPool().GetMemoryStats();
348+
}
349+
335350
void llvm::format_provider<ConstString>::format(const ConstString &CS,
336351
llvm::raw_ostream &OS,
337352
llvm::StringRef Options) {

lldb/test/API/commands/statistics/basic/TestStats.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ def test_default_no_run(self):
135135
136136
(lldb) statistics dump
137137
{
138+
"memory" : {...},
138139
"modules" : [...],
139140
"targets" : [
140141
{
@@ -160,6 +161,7 @@ def test_default_no_run(self):
160161
target = self.createTestTarget()
161162
debug_stats = self.get_stats()
162163
debug_stat_keys = [
164+
'memory',
163165
'modules',
164166
'targets',
165167
'totalSymbolTableParseTime',
@@ -197,6 +199,7 @@ def test_default_with_run(self):
197199
198200
(lldb) statistics dump
199201
{
202+
"memory" : {...},
200203
"modules" : [...],
201204
"targets" : [
202205
{
@@ -227,6 +230,7 @@ def test_default_with_run(self):
227230
lldb.SBFileSpec("main.c"))
228231
debug_stats = self.get_stats()
229232
debug_stat_keys = [
233+
'memory',
230234
'modules',
231235
'targets',
232236
'totalSymbolTableParseTime',
@@ -254,6 +258,44 @@ def test_default_with_run(self):
254258
self.assertGreater(stats['launchOrAttachTime'], 0.0)
255259
self.assertGreater(stats['targetCreateTime'], 0.0)
256260

261+
def test_memory(self):
262+
"""
263+
Test "statistics dump" and the memory information.
264+
"""
265+
exe = self.getBuildArtifact("a.out")
266+
target = self.createTestTarget(file_path=exe)
267+
debug_stats = self.get_stats()
268+
debug_stat_keys = [
269+
'memory',
270+
'modules',
271+
'targets',
272+
'totalSymbolTableParseTime',
273+
'totalSymbolTableIndexTime',
274+
'totalSymbolTablesLoadedFromCache',
275+
'totalSymbolTablesSavedToCache',
276+
'totalDebugInfoParseTime',
277+
'totalDebugInfoIndexTime',
278+
'totalDebugInfoIndexLoadedFromCache',
279+
'totalDebugInfoIndexSavedToCache',
280+
'totalDebugInfoByteSize'
281+
]
282+
self.verify_keys(debug_stats, '"debug_stats"', debug_stat_keys, None)
283+
284+
memory = debug_stats['memory']
285+
memory_keys= [
286+
'strings',
287+
]
288+
self.verify_keys(memory, '"memory"', memory_keys, None)
289+
290+
strings = memory['strings']
291+
strings_keys= [
292+
'bytesTotal',
293+
'bytesUsed',
294+
'bytesUnused',
295+
]
296+
self.verify_keys(strings, '"strings"', strings_keys, None)
297+
298+
257299
def find_module_in_metrics(self, path, stats):
258300
modules = stats['modules']
259301
for module in modules:
@@ -269,6 +311,7 @@ def test_modules(self):
269311
target = self.createTestTarget(file_path=exe)
270312
debug_stats = self.get_stats()
271313
debug_stat_keys = [
314+
'memory',
272315
'modules',
273316
'targets',
274317
'totalSymbolTableParseTime',
@@ -312,6 +355,7 @@ def test_breakpoints(self):
312355
Output expected to be something like:
313356
314357
{
358+
"memory" : {...},
315359
"modules" : [...],
316360
"targets" : [
317361
{
@@ -355,6 +399,7 @@ def test_breakpoints(self):
355399
self.runCmd("b a_function")
356400
debug_stats = self.get_stats()
357401
debug_stat_keys = [
402+
'memory',
358403
'modules',
359404
'targets',
360405
'totalSymbolTableParseTime',

0 commit comments

Comments
 (0)