diff options
author | Elliott Hughes <enh@google.com> | 2013-07-11 18:10:58 -0700 |
---|---|---|
committer | Elliott Hughes <enh@google.com> | 2013-07-11 18:10:58 -0700 |
commit | b1a5879d2c87a5af9f8dbd63a112b138b87135e4 (patch) | |
tree | 663098cb9c72b39ae76f3b8d8dec6b5166772431 | |
parent | d3d41ba95c7760891a1ca4fc02e3f88baaa25dda (diff) | |
download | art-b1a5879d2c87a5af9f8dbd63a112b138b87135e4.zip art-b1a5879d2c87a5af9f8dbd63a112b138b87135e4.tar.gz art-b1a5879d2c87a5af9f8dbd63a112b138b87135e4.tar.bz2 |
Port 1778d17feda232e5f794ba1ebdf400a600a17fd8 to art.
Increase the default alloc tracker maximum, and add a new system
property "dalvik.vm.allocTrackerMax" that allows developers to choose
an arbitrary limit.
Change-Id: I8b3fcfb00ba87d1cf515d5835c101b5375b1d8a2
-rw-r--r-- | src/debugger.cc | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/src/debugger.cc b/src/debugger.cc index d50b55b..4e89838 100644 --- a/src/debugger.cc +++ b/src/debugger.cc @@ -20,6 +20,7 @@ #include <set> +#include "cutils/properties.h" #include "class_linker.h" #include "class_linker-inl.h" #include "dex_file-inl.h" @@ -53,7 +54,7 @@ namespace art { static const size_t kMaxAllocRecordStackDepth = 16; // Max 255. -static const size_t kNumAllocRecords = 512; // Must be a power of 2. +static const size_t kDefaultNumAllocRecords = 64*1024; // Must be a power of 2. struct AllocRecordStackTraceElement { mirror::AbstractMethod* method; @@ -183,6 +184,7 @@ static ObjectRegistry* gRegistry = NULL; // Recent allocation tracking. static Mutex gAllocTrackerLock DEFAULT_MUTEX_ACQUIRED_AFTER ("AllocTracker lock"); AllocRecord* Dbg::recent_allocation_records_ PT_GUARDED_BY(gAllocTrackerLock) = NULL; // TODO: CircularBuffer<AllocRecord> +static size_t gAllocRecordMax GUARDED_BY(gAllocTrackerLock) = 0; static size_t gAllocRecordHead GUARDED_BY(gAllocTrackerLock) = 0; static size_t gAllocRecordCount GUARDED_BY(gAllocTrackerLock) = 0; @@ -3437,15 +3439,38 @@ void Dbg::DdmSendHeapSegments(bool native) { Dbg::DdmSendChunk(native ? CHUNK_TYPE("NHEN") : CHUNK_TYPE("HPEN"), sizeof(heap_id), heap_id); } +static size_t GetAllocTrackerMax() { +#ifdef HAVE_ANDROID_OS + // Check whether there's a system property overriding the number of records. + const char* propertyName = "dalvik.vm.allocTrackerMax"; + char allocRecordMaxString[PROPERTY_VALUE_MAX]; + if (property_get(propertyName, allocRecordMaxString, "") > 0) { + char* end; + size_t value = strtoul(allocRecordMaxString, &end, 10); + if (*end != '\0') { + ALOGE("Ignoring %s '%s' --- invalid", propertyName, allocRecordMaxString); + return kDefaultNumAllocRecords; + } + if (!IsPowerOfTwo(value)) { + ALOGE("Ignoring %s '%s' --- not power of two", propertyName, allocRecordMaxString); + return kDefaultNumAllocRecords; + } + return value; + } +#endif + return kDefaultNumAllocRecords; +} + void Dbg::SetAllocTrackingEnabled(bool enabled) { MutexLock mu(Thread::Current(), gAllocTrackerLock); if (enabled) { if (recent_allocation_records_ == NULL) { - LOG(INFO) << "Enabling alloc tracker (" << kNumAllocRecords << " entries, " - << kMaxAllocRecordStackDepth << " frames --> " - << (sizeof(AllocRecord) * kNumAllocRecords) << " bytes)"; + gAllocRecordMax = GetAllocTrackerMax(); + LOG(INFO) << "Enabling alloc tracker (" << gAllocRecordMax << " entries of " + << kMaxAllocRecordStackDepth << " frames, taking " + << PrettySize(sizeof(AllocRecord) * gAllocRecordMax) << ")"; gAllocRecordHead = gAllocRecordCount = 0; - recent_allocation_records_ = new AllocRecord[kNumAllocRecords]; + recent_allocation_records_ = new AllocRecord[gAllocRecordMax]; CHECK(recent_allocation_records_ != NULL); } } else { @@ -3496,7 +3521,7 @@ void Dbg::RecordAllocation(mirror::Class* type, size_t byte_count) { } // Advance and clip. - if (++gAllocRecordHead == kNumAllocRecords) { + if (++gAllocRecordHead == gAllocRecordMax) { gAllocRecordHead = 0; } @@ -3510,7 +3535,7 @@ void Dbg::RecordAllocation(mirror::Class* type, size_t byte_count) { AllocRecordStackVisitor visitor(self, record); visitor.WalkStack(); - if (gAllocRecordCount < kNumAllocRecords) { + if (gAllocRecordCount < gAllocRecordMax) { ++gAllocRecordCount; } } @@ -3522,9 +3547,9 @@ void Dbg::RecordAllocation(mirror::Class* type, size_t byte_count) { // from it. // // We need to handle underflow in our circular buffer, so we add -// kNumAllocRecords and then mask it back down. +// gAllocRecordMax and then mask it back down. static inline int HeadIndex() EXCLUSIVE_LOCKS_REQUIRED(gAllocTrackerLock) { - return (gAllocRecordHead+1 + kNumAllocRecords - gAllocRecordCount) & (kNumAllocRecords-1); + return (gAllocRecordHead+1 + gAllocRecordMax - gAllocRecordCount) & (gAllocRecordMax-1); } void Dbg::DumpRecentAllocations() { @@ -3560,7 +3585,7 @@ void Dbg::DumpRecentAllocations() { usleep(40000); } - i = (i + 1) & (kNumAllocRecords-1); + i = (i + 1) & (gAllocRecordMax-1); } } @@ -3632,7 +3657,7 @@ class StringTable { * followed by UTF-16 data. * * We send up 16-bit unsigned indexes into string tables. In theory there - * can be (kMaxAllocRecordStackDepth * kNumAllocRecords) unique strings in + * can be (kMaxAllocRecordStackDepth * gAllocRecordMax) unique strings in * each table, but in practice there should be far fewer. * * The chief reason for using a string table here is to keep the size of @@ -3678,7 +3703,7 @@ jbyteArray Dbg::GetRecentAllocations() { } } - idx = (idx + 1) & (kNumAllocRecords-1); + idx = (idx + 1) & (gAllocRecordMax-1); } LOG(INFO) << "allocation records: " << gAllocRecordCount; @@ -3744,7 +3769,7 @@ jbyteArray Dbg::GetRecentAllocations() { JDWP::Append2BE(bytes, record->stack[stack_frame].LineNumber()); } - idx = (idx + 1) & (kNumAllocRecords-1); + idx = (idx + 1) & (gAllocRecordMax-1); } // (xb) class name strings |