Add max post-gc heap usage metrics
- Add per heap max usage metrics.
- Add combined heap (max) usage metrics.
Fixes #24483
R=koda@google.com
Review URL: https://codereview.chromium.org/1384003004 .
diff --git a/runtime/vm/heap.cc b/runtime/vm/heap.cc
index 39d3478..670c868 100644
--- a/runtime/vm/heap.cc
+++ b/runtime/vm/heap.cc
@@ -453,6 +453,16 @@
}
+void Heap::UpdateGlobalMaxUsed() {
+ ASSERT(isolate_ != NULL);
+ // We are accessing the used in words count for both new and old space
+ // without synchronizing. The value of this metric is approximate.
+ isolate_->GetHeapGlobalUsedMaxMetric()->SetValue(
+ (UsedInWords(Heap::kNew) * kWordSize) +
+ (UsedInWords(Heap::kOld) * kWordSize));
+}
+
+
void Heap::SetGrowthControlState(bool state) {
old_space_.SetGrowthControlState(state);
}
@@ -568,8 +578,8 @@
void Heap::PrintSizes() const {
- OS::PrintErr("New space (%" Pd "k of %" Pd "k) "
- "Old space (%" Pd "k of %" Pd "k)\n",
+ OS::PrintErr("New space (%" Pd64 "k of %" Pd64 "k) "
+ "Old space (%" Pd64 "k of %" Pd64 "k)\n",
(UsedInWords(kNew) / KBInWords),
(CapacityInWords(kNew) / KBInWords),
(UsedInWords(kOld) / KBInWords),
@@ -577,21 +587,23 @@
}
-intptr_t Heap::UsedInWords(Space space) const {
+int64_t Heap::UsedInWords(Space space) const {
return space == kNew ? new_space_.UsedInWords() : old_space_.UsedInWords();
}
-intptr_t Heap::CapacityInWords(Space space) const {
+int64_t Heap::CapacityInWords(Space space) const {
return space == kNew ? new_space_.CapacityInWords() :
old_space_.CapacityInWords();
}
-intptr_t Heap::ExternalInWords(Space space) const {
+
+int64_t Heap::ExternalInWords(Space space) const {
return space == kNew ? new_space_.ExternalInWords() :
old_space_.ExternalInWords();
}
+
int64_t Heap::GCTimeInMicros(Space space) const {
if (space == kNew) {
return new_space_.gc_time_micros();
diff --git a/runtime/vm/heap.h b/runtime/vm/heap.h
index 496a9c8..4639c26 100644
--- a/runtime/vm/heap.h
+++ b/runtime/vm/heap.h
@@ -158,9 +158,9 @@
void PrintSizes() const;
// Return amount of memory used and capacity in a space, excluding external.
- intptr_t UsedInWords(Space space) const;
- intptr_t CapacityInWords(Space space) const;
- intptr_t ExternalInWords(Space space) const;
+ int64_t UsedInWords(Space space) const;
+ int64_t CapacityInWords(Space space) const;
+ int64_t ExternalInWords(Space space) const;
// Return the amount of GCing in microseconds.
int64_t GCTimeInMicros(Space space) const;
@@ -222,6 +222,8 @@
bool gc_in_progress();
+ void UpdateGlobalMaxUsed();
+
static bool IsAllocatableInNewSpace(intptr_t size) {
return size <= kNewAllocatableSize;
}
diff --git a/runtime/vm/metrics.cc b/runtime/vm/metrics.cc
index 274a3fd..0e15c0f 100644
--- a/runtime/vm/metrics.cc
+++ b/runtime/vm/metrics.cc
@@ -276,6 +276,12 @@
}
+int64_t MetricHeapUsed::Value() const {
+ ASSERT(isolate() == Isolate::Current());
+ return isolate()->heap()->UsedInWords(Heap::kNew) * kWordSize +
+ isolate()->heap()->UsedInWords(Heap::kOld) * kWordSize;
+}
+
int64_t MetricIsolateCount::Value() const {
return Isolate::IsolateListLength();
}
diff --git a/runtime/vm/metrics.h b/runtime/vm/metrics.h
index 22f9a78..9fde2d8 100644
--- a/runtime/vm/metrics.h
+++ b/runtime/vm/metrics.h
@@ -15,13 +15,17 @@
// Metrics for each isolate.
#define ISOLATE_METRIC_LIST(V) \
V(MetricHeapOldUsed, HeapOldUsed, "heap.old.used", kByte) \
+ V(MaxMetric, HeapOldUsedMax, "heap.old.used.max", kByte) \
V(MetricHeapOldCapacity, HeapOldCapacity, "heap.old.capacity", kByte) \
V(MaxMetric, HeapOldCapacityMax, "heap.old.capacity.max", kByte) \
V(MetricHeapOldExternal, HeapOldExternal, "heap.old.external", kByte) \
V(MetricHeapNewUsed, HeapNewUsed, "heap.new.used", kByte) \
+ V(MaxMetric, HeapNewUsedMax, "heap.new.used.max", kByte) \
V(MetricHeapNewCapacity, HeapNewCapacity, "heap.new.capacity", kByte) \
V(MaxMetric, HeapNewCapacityMax, "heap.new.capacity.max", kByte) \
- V(MetricHeapNewExternal, HeapNewExternal, "heap.new.external", kByte)
+ V(MetricHeapNewExternal, HeapNewExternal, "heap.new.external", kByte) \
+ V(MetricHeapUsed, HeapGlobalUsed, "heap.global.used", kByte) \
+ V(MaxMetric, HeapGlobalUsedMax, "heap.global.used.max", kByte) \
#define VM_METRIC_LIST(V) \
V(MetricIsolateCount, IsolateCount, "vm.isolate.count", kCounter)
@@ -166,6 +170,11 @@
};
+class MetricHeapUsed : public Metric {
+ protected:
+ virtual int64_t Value() const;
+};
+
} // namespace dart
#endif // VM_METRICS_H_
diff --git a/runtime/vm/pages.cc b/runtime/vm/pages.cc
index 7cee6df..da7ec80 100644
--- a/runtime/vm/pages.cc
+++ b/runtime/vm/pages.cc
@@ -171,6 +171,7 @@
collections_(0) {
// We aren't holding the lock but no one can reference us yet.
UpdateMaxCapacityLocked();
+ UpdateMaxUsed();
}
@@ -547,6 +548,19 @@
}
+void PageSpace::UpdateMaxUsed() {
+ if (heap_ == NULL) {
+ // Some unit tests.
+ return;
+ }
+ ASSERT(heap_ != NULL);
+ ASSERT(heap_->isolate() != NULL);
+ Isolate* isolate = heap_->isolate();
+ isolate->GetHeapOldUsedMaxMetric()->SetValue(
+ UsedInWords() * kWordSize);
+}
+
+
bool PageSpace::Contains(uword addr) const {
for (ExclusivePageIterator it(this); !it.Done(); it.Advance()) {
if (it.page()->Contains(addr)) {
@@ -662,9 +676,9 @@
space.AddProperty("name", "old");
space.AddProperty("vmName", "PageSpace");
space.AddProperty("collections", collections());
- space.AddProperty("used", UsedInWords() * kWordSize);
- space.AddProperty("capacity", CapacityInWords() * kWordSize);
- space.AddProperty("external", ExternalInWords() * kWordSize);
+ space.AddProperty64("used", UsedInWords() * kWordSize);
+ space.AddProperty64("capacity", CapacityInWords() * kWordSize);
+ space.AddProperty64("external", ExternalInWords() * kWordSize);
space.AddProperty("time", MicrosecondsToSeconds(gc_time_micros()));
if (collections() > 0) {
int64_t run_time = OS::GetCurrentTimeMicros() - isolate->start_time();
@@ -932,6 +946,11 @@
freelist_[HeapPage::kExecutable].Print();
}
+ UpdateMaxUsed();
+ if (heap_ != NULL) {
+ heap_->UpdateGlobalMaxUsed();
+ }
+
isolate->thread_registry()->ResumeAllThreads();
// Done, reset the task count.
diff --git a/runtime/vm/pages.h b/runtime/vm/pages.h
index 7cc123b6..39ef84e 100644
--- a/runtime/vm/pages.h
+++ b/runtime/vm/pages.h
@@ -218,8 +218,8 @@
NeedsExternalGC();
}
- intptr_t UsedInWords() const { return usage_.used_in_words; }
- intptr_t CapacityInWords() const {
+ int64_t UsedInWords() const { return usage_.used_in_words; }
+ int64_t CapacityInWords() const {
MutexLocker ml(pages_lock_);
return usage_.capacity_in_words;
}
@@ -234,8 +234,9 @@
}
void UpdateMaxCapacityLocked();
+ void UpdateMaxUsed();
- intptr_t ExternalInWords() const {
+ int64_t ExternalInWords() const {
return usage_.external_in_words;
}
SpaceUsage GetCurrentUsage() const {
diff --git a/runtime/vm/scavenger.cc b/runtime/vm/scavenger.cc
index e885b98..f526af1 100644
--- a/runtime/vm/scavenger.cc
+++ b/runtime/vm/scavenger.cc
@@ -415,13 +415,18 @@
if (to_ == NULL) {
FATAL("Out of memory.\n");
}
- UpdateMaxHeapCapacity();
// Setup local fields.
top_ = FirstObjectStart();
resolved_top_ = top_;
end_ = to_->end();
survivor_end_ = FirstObjectStart();
+
+ UpdateMaxHeapCapacity();
+ UpdateMaxHeapUsage();
+ if (heap_ != NULL) {
+ heap_->UpdateGlobalMaxUsed();
+ }
}
@@ -501,6 +506,10 @@
}
#endif // defined(DEBUG)
from->Delete();
+ UpdateMaxHeapUsage();
+ if (heap_ != NULL) {
+ heap_->UpdateGlobalMaxUsed();
+ }
if (invoke_api_callbacks && (isolate->gc_epilogue_callback() != NULL)) {
(isolate->gc_epilogue_callback())();
}
@@ -720,6 +729,19 @@
}
+void Scavenger::UpdateMaxHeapUsage() {
+ if (heap_ == NULL) {
+ // Some unit tests.
+ return;
+ }
+ ASSERT(to_ != NULL);
+ ASSERT(heap_ != NULL);
+ Isolate* isolate = heap_->isolate();
+ ASSERT(isolate != NULL);
+ isolate->GetHeapNewUsedMaxMetric()->SetValue(UsedInWords() * kWordSize);
+}
+
+
uword Scavenger::ProcessWeakProperty(RawWeakProperty* raw_weak,
ScavengerVisitor* visitor) {
// The fate of the weak property is determined by its key.
@@ -916,9 +938,9 @@
} else {
space.AddProperty("avgCollectionPeriodMillis", 0.0);
}
- space.AddProperty("used", UsedInWords() * kWordSize);
- space.AddProperty("capacity", CapacityInWords() * kWordSize);
- space.AddProperty("external", ExternalInWords() * kWordSize);
+ space.AddProperty64("used", UsedInWords() * kWordSize);
+ space.AddProperty64("capacity", CapacityInWords() * kWordSize);
+ space.AddProperty64("external", ExternalInWords() * kWordSize);
space.AddProperty("time", MicrosecondsToSeconds(gc_time_micros()));
}
diff --git a/runtime/vm/scavenger.h b/runtime/vm/scavenger.h
index d265ab9..af3f129 100644
--- a/runtime/vm/scavenger.h
+++ b/runtime/vm/scavenger.h
@@ -164,13 +164,13 @@
static intptr_t top_offset() { return OFFSET_OF(Scavenger, top_); }
static intptr_t end_offset() { return OFFSET_OF(Scavenger, end_); }
- intptr_t UsedInWords() const {
+ int64_t UsedInWords() const {
return (top_ - FirstObjectStart()) >> kWordSizeLog2;
}
- intptr_t CapacityInWords() const {
+ int64_t CapacityInWords() const {
return to_->size_in_words();
}
- intptr_t ExternalInWords() const {
+ int64_t ExternalInWords() const {
return external_size_ >> kWordSizeLog2;
}
SpaceUsage GetCurrentUsage() const {
@@ -269,6 +269,7 @@
}
void UpdateMaxHeapCapacity();
+ void UpdateMaxHeapUsage();
void ProcessWeakTables();