diff options
author | 2012-04-16 10:23:15 -0700 | |
---|---|---|
committer | 2012-04-16 10:23:15 -0700 | |
commit | c967f78cd29b6019f7cfca40a02e9b677112da70 (patch) | |
tree | 60458d56fc398c9fb7b67b6d834b85f626ac2b31 | |
parent | fd8ea97f64fb6d32cbfe35729b816a22dfa18224 (diff) |
Include a new heap summary line in the SIGQUIT output.
Looks like this:
Heap: 87% free, 4MB/32MB; 6327 objects
While I'm here, fix another long-standing TODO to make PrettySize have the
usual google3 behavior. (I took the specific thresholds from Chromium.)
Also distinguish between the more general "Dump" member functions and the
specific SIGQUIT-related ones by consistently calling the latter DumpForSigQuit.
Change-Id: I76e783adc18dd089bac9b348f53dc9860a0fe4b9
-rw-r--r-- | src/heap.cc | 21 | ||||
-rw-r--r-- | src/heap.h | 5 | ||||
-rw-r--r-- | src/runtime.cc | 6 | ||||
-rw-r--r-- | src/runtime.h | 2 | ||||
-rw-r--r-- | src/signal_catcher.cc | 2 | ||||
-rw-r--r-- | src/thread_list.cc | 2 | ||||
-rw-r--r-- | src/thread_list.h | 2 | ||||
-rw-r--r-- | src/utils.cc | 28 | ||||
-rw-r--r-- | src/utils.h | 2 | ||||
-rw-r--r-- | src/utils_test.cc | 6 |
10 files changed, 49 insertions, 27 deletions
diff --git a/src/heap.cc b/src/heap.cc index eb62807c23..b4bc7cee85 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -641,16 +641,10 @@ void Heap::CollectGarbageInternal(bool clear_soft_references) { if (VLOG_IS_ON(gc) || gc_was_particularly_slow) { // TODO: somehow make the specific GC implementation (here MarkSweep) responsible for logging. size_t bytes_freed = initial_size - num_bytes_allocated_; - if (bytes_freed > KB) { // ignore freed bytes in output if > 1KB - bytes_freed = RoundDown(bytes_freed, KB); - } - size_t bytes_allocated = RoundUp(num_bytes_allocated_, KB); // lose low nanoseconds in duration. TODO: make this part of PrettyDuration duration_ns = (duration_ns / 1000) * 1000; - size_t total = GetTotalMemory(); - size_t percentFree = 100 - static_cast<size_t>(100.0f * static_cast<float>(num_bytes_allocated_) / total); - LOG(INFO) << "GC freed " << PrettySize(bytes_freed) << ", " << percentFree << "% free, " - << PrettySize(bytes_allocated) << "/" << PrettySize(total) << ", " + LOG(INFO) << "GC freed " << PrettySize(bytes_freed) << ", " << GetPercentFree() << "% free, " + << PrettySize(num_bytes_allocated_) << "/" << PrettySize(GetTotalMemory()) << ", " << "paused " << PrettyDuration(duration_ns); } Dbg::GcDidFinish(); @@ -663,6 +657,17 @@ void Heap::WaitForConcurrentGcToComplete() { lock_->AssertHeld(); } +void Heap::DumpForSigQuit(std::ostream& os) { + os << "Heap: " << GetPercentFree() << "% free, " + << PrettySize(num_bytes_allocated_) << "/" << PrettySize(GetTotalMemory()) + << "; " << num_objects_allocated_ << " objects"; +} + +size_t Heap::GetPercentFree() { + size_t total = GetTotalMemory(); + return 100 - static_cast<size_t>(100.0f * static_cast<float>(num_bytes_allocated_) / total); +} + void Heap::SetIdealFootprint(size_t max_allowed_footprint) { size_t alloc_space_capacity = alloc_space_->Capacity(); if (max_allowed_footprint > alloc_space_capacity) { diff --git a/src/heap.h b/src/heap.h index 77178711b9..3f0ffc0ec3 100644 --- a/src/heap.h +++ b/src/heap.h @@ -17,6 +17,7 @@ #ifndef ART_SRC_HEAP_H_ #define ART_SRC_HEAP_H_ +#include <iosfwd> #include <string> #include <vector> @@ -219,6 +220,8 @@ class Heap { return alloc_space_; } + void DumpForSigQuit(std::ostream& os); + private: // Allocates uninitialized storage. Object* AllocateLocked(size_t num_bytes); @@ -239,6 +242,8 @@ class Heap { // collection. void GrowForUtilization(); + size_t GetPercentFree(); + void AddSpace(Space* space); void VerifyObjectLocked(const Object *obj); diff --git a/src/runtime.cc b/src/runtime.cc index 77c887e6f1..947eec5ea4 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -745,13 +745,13 @@ void Runtime::RegisterRuntimeNativeMethods(JNIEnv* env) { #undef REGISTER } -void Runtime::Dump(std::ostream& os) { - // TODO: dump other runtime statistics? +void Runtime::DumpForSigQuit(std::ostream& os) { GetClassLinker()->DumpForSigQuit(os); GetInternTable()->DumpForSigQuit(os); + GetHeap()->DumpForSigQuit(os); os << "\n"; - thread_list_->Dump(os); + thread_list_->DumpForSigQuit(os); } void Runtime::DumpLockHolders(std::ostream& os) { diff --git a/src/runtime.h b/src/runtime.h index 0dea7630d5..2bf1148d17 100644 --- a/src/runtime.h +++ b/src/runtime.h @@ -130,7 +130,7 @@ class Runtime { // Detaches the current native thread from the runtime. void DetachCurrentThread(); - void Dump(std::ostream& os); + void DumpForSigQuit(std::ostream& os); void DumpLockHolders(std::ostream& os); ~Runtime(); diff --git a/src/signal_catcher.cc b/src/signal_catcher.cc index be213729cd..dd31fa762d 100644 --- a/src/signal_catcher.cc +++ b/src/signal_catcher.cc @@ -114,7 +114,7 @@ void SignalCatcher::HandleSigQuit() { os << "Cmd line: " << cmdline << "\n"; } - runtime->Dump(os); + runtime->DumpForSigQuit(os); if (false) { std::string maps; diff --git a/src/thread_list.cc b/src/thread_list.cc index 43a856181d..80ab2cfc60 100644 --- a/src/thread_list.cc +++ b/src/thread_list.cc @@ -54,7 +54,7 @@ pid_t ThreadList::GetLockOwner() { return thread_list_lock_.GetOwner(); } -void ThreadList::Dump(std::ostream& os) { +void ThreadList::DumpForSigQuit(std::ostream& os) { ScopedThreadListLock thread_list_lock; DumpLocked(os); } diff --git a/src/thread_list.h b/src/thread_list.h index 0691808649..f0b4f6bc7a 100644 --- a/src/thread_list.h +++ b/src/thread_list.h @@ -31,7 +31,7 @@ class ThreadList { explicit ThreadList(); ~ThreadList(); - void Dump(std::ostream& os); + void DumpForSigQuit(std::ostream& os); void DumpLocked(std::ostream& os); // For thread suspend timeout dumps. pid_t GetLockOwner(); // For SignalCatcher. diff --git a/src/utils.cc b/src/utils.cc index 70d15bf3e9..ea50073b42 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -345,16 +345,26 @@ std::string PrettyClassAndClassLoader(const Class* c) { return result; } -std::string PrettySize(size_t size_in_bytes) { - if ((size_in_bytes / GB) * GB == size_in_bytes) { - return StringPrintf("%zdGB", size_in_bytes / GB); - } else if ((size_in_bytes / MB) * MB == size_in_bytes) { - return StringPrintf("%zdMB", size_in_bytes / MB); - } else if ((size_in_bytes / KB) * KB == size_in_bytes) { - return StringPrintf("%zdKB", size_in_bytes / KB); - } else { - return StringPrintf("%zdB", size_in_bytes); +std::string PrettySize(size_t byte_count) { + // The byte thresholds at which we display amounts. A byte count is displayed + // in unit U when kUnitThresholds[U] <= bytes < kUnitThresholds[U+1]. + static const size_t kUnitThresholds[] = { + 0, // B up to... + 3*1024, // KB up to... + 2*1024*1024, // MB up to... + 1024*1024*1024 // GB from here. + }; + static const size_t kBytesPerUnit[] = { 1, KB, MB, GB }; + static const char* const kUnitStrings[] = { "B", "KB", "MB", "GB" }; + + int i = arraysize(kUnitThresholds); + while (--i > 0) { + if (byte_count >= kUnitThresholds[i]) { + break; + } } + + return StringPrintf("%zd%s", byte_count / kBytesPerUnit[i], kUnitStrings[i]); } std::string PrettyDuration(uint64_t nano_duration) { diff --git a/src/utils.h b/src/utils.h index f11a769fd3..f94c05ec97 100644 --- a/src/utils.h +++ b/src/utils.h @@ -191,7 +191,7 @@ std::string PrettyClass(const Class* c); // Returns a human-readable form of the name of the given class with its class loader. std::string PrettyClassAndClassLoader(const Class* c); -// Returns a human-readable size string. e.g. "1MB" +// Returns a human-readable size string such as "1MB". std::string PrettySize(size_t size_in_bytes); // Returns a human-readable time string which prints every nanosecond while trying to limit the diff --git a/src/utils_test.cc b/src/utils_test.cc index e0b2139999..311bd16aaa 100644 --- a/src/utils_test.cc +++ b/src/utils_test.cc @@ -135,15 +135,17 @@ TEST_F(UtilsTest, PrettySize) { if (sizeof(size_t) > sizeof(uint32_t)) { EXPECT_EQ("100GB", PrettySize(100 * GB)); } - EXPECT_EQ("1MB", PrettySize(1 * MB)); + EXPECT_EQ("1024KB", PrettySize(1 * MB)); EXPECT_EQ("10MB", PrettySize(10 * MB)); EXPECT_EQ("100MB", PrettySize(100 * MB)); - EXPECT_EQ("1KB", PrettySize(1 * KB)); + EXPECT_EQ("1024B", PrettySize(1 * KB)); EXPECT_EQ("10KB", PrettySize(10 * KB)); EXPECT_EQ("100KB", PrettySize(100 * KB)); + EXPECT_EQ("0B", PrettySize(0)); EXPECT_EQ("1B", PrettySize(1)); EXPECT_EQ("10B", PrettySize(10)); EXPECT_EQ("100B", PrettySize(100)); + EXPECT_EQ("512B", PrettySize(512)); } TEST_F(UtilsTest, PrettyDuration) { |