ART: Improve Dbg::GetRecentAllocations
Move ClassTable to const char* instead of std::string, and let it
know when it needs to keep a copy of the string itself. This avoids
lots of temporary allocations.
Increase the stack depth in test 098 to better cover this behavior.
Add allocations of proxies and arrays to cover the backing storage.
Improvements on test 098:
Before:
heaptrack stats:
allocations: 598174
leaked allocations: 186
temporary allocations: 132302
65797 calls to allocation functions with 3.34KB peak consumption from
art::StringTable::Add(char const*)
65666 calls to allocation functions with 144B peak consumption from
art::StringTable::IndexOf(char const*) const
After:
heaptrack stats:
allocations: 466828
leaked allocations: 186
temporary allocations: 1002
Bug: 37620770
Test: m test-art-host
Test: art/test/testrunner/testrunner.py -b --host -t 098
Test: SANITIZE_HOST=address art/test/testrunner/testrunner.py -b --host -t 098
Change-Id: Iee496c96471dbb825c22b2656598c95f7c029a2f
diff --git a/runtime/debugger.cc b/runtime/debugger.cc
index c94a8e0..b595112 100644
--- a/runtime/debugger.cc
+++ b/runtime/debugger.cc
@@ -18,7 +18,9 @@
#include <sys/uio.h>
+#include <memory>
#include <set>
+#include <vector>
#include "android-base/stringprintf.h"
@@ -26,6 +28,7 @@
#include "art_field-inl.h"
#include "art_method-inl.h"
#include "base/enums.h"
+#include "base/strlcpy.h"
#include "base/time_utils.h"
#include "class_linker.h"
#include "class_linker-inl.h"
@@ -4926,11 +4929,20 @@
StringTable() {
}
- void Add(const std::string& str) {
- table_.insert(str);
- }
+ void Add(const char* str, bool copy_string) {
+ if (UNLIKELY(copy_string)) {
+ // Check whether it's already there.
+ if (table_.find(str) != table_.end()) {
+ return;
+ }
- void Add(const char* str) {
+ // Make a copy.
+ size_t str_len = strlen(str);
+ char* copy = new char[str_len + 1];
+ strlcpy(copy, str, str_len + 1);
+ string_backup_.emplace_back(copy);
+ str = copy;
+ }
table_.insert(str);
}
@@ -4947,17 +4959,23 @@
}
void WriteTo(std::vector<uint8_t>& bytes) const {
- for (const std::string& str : table_) {
- const char* s = str.c_str();
- size_t s_len = CountModifiedUtf8Chars(s);
+ for (const char* str : table_) {
+ size_t s_len = CountModifiedUtf8Chars(str);
std::unique_ptr<uint16_t[]> s_utf16(new uint16_t[s_len]);
- ConvertModifiedUtf8ToUtf16(s_utf16.get(), s);
+ ConvertModifiedUtf8ToUtf16(s_utf16.get(), str);
JDWP::AppendUtf16BE(bytes, s_utf16.get(), s_len);
}
}
private:
- std::set<std::string> table_;
+ struct ConstCharStarComparator {
+ bool operator()(const char *s1, const char *s2) const {
+ return strcmp(s1, s2) < 0;
+ }
+ };
+
+ std::set<const char*, ConstCharStarComparator> table_;
+ std::vector<std::unique_ptr<char[]>> string_backup_;
DISALLOW_COPY_AND_ASSIGN(StringTable);
};
@@ -5044,12 +5062,13 @@
count > 0 && it != end; count--, it++) {
const gc::AllocRecord* record = &it->second;
std::string temp;
- class_names.Add(record->GetClassDescriptor(&temp));
+ const char* class_descr = record->GetClassDescriptor(&temp);
+ class_names.Add(class_descr, !temp.empty());
for (size_t i = 0, depth = record->GetDepth(); i < depth; i++) {
ArtMethod* m = record->StackElement(i).GetMethod();
- class_names.Add(m->GetDeclaringClassDescriptor());
- method_names.Add(m->GetName());
- filenames.Add(GetMethodSourceFile(m));
+ class_names.Add(m->GetDeclaringClassDescriptor(), false);
+ method_names.Add(m->GetName(), false);
+ filenames.Add(GetMethodSourceFile(m), false);
}
}