diff options
| -rw-r--r-- | runtime/gc/heap.cc | 31 | ||||
| -rw-r--r-- | runtime/gc/heap.h | 39 |
2 files changed, 38 insertions, 32 deletions
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc index 6d8190ed02..1ea514b3b2 100644 --- a/runtime/gc/heap.cc +++ b/runtime/gc/heap.cc @@ -787,10 +787,15 @@ void Heap::DumpGcPerformanceInfo(std::ostream& os) { os << "Mean GC object throughput: " << (GetObjectsFreedEver() / total_seconds) << " objects/s\n"; } - size_t total_objects_allocated = GetObjectsAllocatedEver(); + uint64_t total_objects_allocated = GetObjectsAllocatedEver(); os << "Total number of allocations: " << total_objects_allocated << "\n"; - size_t total_bytes_allocated = GetBytesAllocatedEver(); + uint64_t total_bytes_allocated = GetBytesAllocatedEver(); os << "Total bytes allocated " << PrettySize(total_bytes_allocated) << "\n"; + os << "Free memory" << PrettySize(GetFreeMemoryUntilGC()) << "\n"; + os << "Free memory until GC " << PrettySize(GetFreeMemoryUntilGC()) << "\n"; + os << "Free memory until OOME " << PrettySize(GetFreeMemoryUntilOOME()) << "\n"; + os << "Total memory" << PrettySize(GetTotalMemory()) << "\n"; + os << "Max memory" << PrettySize(GetMaxMemory()) << "\n"; if (kMeasureAllocationTime) { os << "Total time spent allocating: " << PrettyDuration(allocation_time) << "\n"; os << "Mean allocation time: " << PrettyDuration(allocation_time / total_objects_allocated) @@ -864,7 +869,7 @@ void Heap::ThrowOutOfMemoryError(Thread* self, size_t byte_count, AllocatorType std::ostringstream oss; size_t total_bytes_free = GetFreeMemory(); oss << "Failed to allocate a " << byte_count << " byte allocation with " << total_bytes_free - << " free bytes"; + << " free bytes and " << PrettySize(GetFreeMemoryUntilOOME()) << " until OOM"; // If the allocation failed due to fragmentation, print out the largest continuous allocation. if (total_bytes_free >= byte_count) { space::AllocSpace* space = nullptr; @@ -1313,11 +1318,11 @@ size_t Heap::GetObjectsAllocated() const { return total; } -size_t Heap::GetObjectsAllocatedEver() const { +uint64_t Heap::GetObjectsAllocatedEver() const { return GetObjectsFreedEver() + GetObjectsAllocated(); } -size_t Heap::GetBytesAllocatedEver() const { +uint64_t Heap::GetBytesAllocatedEver() const { return GetBytesFreedEver() + GetBytesAllocated(); } @@ -2847,7 +2852,7 @@ void Heap::GrowForUtilization(collector::GarbageCollector* collector_ran) { remaining_bytes = kMinConcurrentRemainingBytes; } DCHECK_LE(remaining_bytes, max_allowed_footprint_); - DCHECK_LE(max_allowed_footprint_, growth_limit_); + DCHECK_LE(max_allowed_footprint_, GetMaxMemory()); // Start a concurrent GC when we get close to the estimated remaining bytes. When the // allocation rate is very high, remaining_bytes could tell us that we should start a GC // right away. @@ -3077,19 +3082,7 @@ void Heap::RegisterNativeFree(JNIEnv* env, int bytes) { } size_t Heap::GetTotalMemory() const { - size_t ret = 0; - for (const auto& space : continuous_spaces_) { - // Currently don't include the image space. - if (!space->IsImageSpace()) { - ret += space->Size(); - } - } - for (const auto& space : discontinuous_spaces_) { - if (space->IsLargeObjectSpace()) { - ret += space->AsLargeObjectSpace()->GetBytesAllocated(); - } - } - return ret; + return std::max(max_allowed_footprint_, GetBytesAllocated()); } void Heap::AddModUnionTable(accounting::ModUnionTable* mod_union_table) { diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h index 1851662669..d5b49d81cf 100644 --- a/runtime/gc/heap.h +++ b/runtime/gc/heap.h @@ -401,18 +401,18 @@ class Heap { size_t GetObjectsAllocated() const LOCKS_EXCLUDED(Locks::heap_bitmap_lock_); // Returns the total number of objects allocated since the heap was created. - size_t GetObjectsAllocatedEver() const; + uint64_t GetObjectsAllocatedEver() const; // Returns the total number of bytes allocated since the heap was created. - size_t GetBytesAllocatedEver() const; + uint64_t GetBytesAllocatedEver() const; // Returns the total number of objects freed since the heap was created. - size_t GetObjectsFreedEver() const { + uint64_t GetObjectsFreedEver() const { return total_objects_freed_ever_; } // Returns the total number of bytes freed since the heap was created. - size_t GetBytesFreedEver() const { + uint64_t GetBytesFreedEver() const { return total_bytes_freed_ever_; } @@ -421,19 +421,32 @@ class Heap { // were specified. Android apps start with a growth limit (small heap size) which is // cleared/extended for large apps. size_t GetMaxMemory() const { - return growth_limit_; + // There is some race conditions in the allocation code that can cause bytes allocated to + // become larger than growth_limit_ in rare cases. + return std::max(GetBytesAllocated(), growth_limit_); } - // Implements java.lang.Runtime.totalMemory, returning the amount of memory consumed by an - // application. + // Implements java.lang.Runtime.totalMemory, returning approximate amount of memory currently + // consumed by an application. size_t GetTotalMemory() const; - // Implements java.lang.Runtime.freeMemory. + // Returns approximately how much free memory we have until the next GC happens. + size_t GetFreeMemoryUntilGC() const { + return max_allowed_footprint_ - GetBytesAllocated(); + } + + // Returns approximately how much free memory we have until the next OOME happens. + size_t GetFreeMemoryUntilOOME() const { + return growth_limit_ - GetBytesAllocated(); + } + + // Returns how much free memory we have until we need to grow the heap to perform an allocation. + // Similar to GetFreeMemoryUntilGC. Implements java.lang.Runtime.freeMemory. size_t GetFreeMemory() const { size_t byte_allocated = num_bytes_allocated_.LoadSequentiallyConsistent(); - // Make sure we don't get a negative number since the max allowed footprint is only updated - // after the GC. But we can still allocate even if bytes_allocated > max_allowed_footprint_. - return std::max(max_allowed_footprint_, byte_allocated) - byte_allocated; + size_t total_memory = GetTotalMemory(); + // Make sure we don't get a negative number. + return total_memory - std::min(total_memory, byte_allocated); } // get the space that corresponds to an object's address. Current implementation searches all @@ -885,10 +898,10 @@ class Heap { size_t concurrent_start_bytes_; // Since the heap was created, how many bytes have been freed. - size_t total_bytes_freed_ever_; + uint64_t total_bytes_freed_ever_; // Since the heap was created, how many objects have been freed. - size_t total_objects_freed_ever_; + uint64_t total_objects_freed_ever_; // Number of bytes allocated. Adjusted after each allocation and free. Atomic<size_t> num_bytes_allocated_; |