Commit ae893000 authored by Omer Katz's avatar Omer Katz Committed by Commit Bot

cppgc: Add object/memory size histograms for UMA

Bug: chromium:1056170
Change-Id: I3d6cbff3e37bb541481a014056e539bd4824c37c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2642259
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72266}
parent 0ac80246
......@@ -15,6 +15,7 @@
#include "src/heap/cppgc/object-start-bitmap.h"
#include "src/heap/cppgc/page-memory.h"
#include "src/heap/cppgc/raw-heap.h"
#include "src/heap/cppgc/stats-collector.h"
namespace cppgc {
namespace internal {
......@@ -123,6 +124,7 @@ void NormalPage::Destroy(NormalPage* page) {
DCHECK_EQ(space->end(), std::find(space->begin(), space->end(), page));
page->~NormalPage();
PageBackend* backend = page->heap()->page_backend();
page->heap()->stats_collector()->NotifyFreedMemory(kPageSize);
backend->FreeNormalPageMemory(space->index(),
reinterpret_cast<Address>(page));
}
......@@ -176,6 +178,14 @@ LargePage::LargePage(HeapBase* heap, BaseSpace* space, size_t size)
LargePage::~LargePage() = default;
namespace {
size_t LargePageAllocationSize(size_t payload_size) {
const size_t page_header_size =
RoundUp(sizeof(LargePage), kAllocationGranularity);
return page_header_size + payload_size;
}
} // namespace
// static
LargePage* LargePage::Create(PageBackend* page_backend, LargePageSpace* space,
size_t size) {
......@@ -183,9 +193,7 @@ LargePage* LargePage::Create(PageBackend* page_backend, LargePageSpace* space,
DCHECK_NOT_NULL(space);
DCHECK_LE(kLargeObjectSizeThreshold, size);
const size_t page_header_size =
RoundUp(sizeof(LargePage), kAllocationGranularity);
const size_t allocation_size = page_header_size + size;
const size_t allocation_size = LargePageAllocationSize(size);
auto* heap = space->raw_heap()->heap();
void* memory = page_backend->AllocateLargePageMemory(allocation_size);
......@@ -203,6 +211,8 @@ void LargePage::Destroy(LargePage* page) {
#endif
page->~LargePage();
PageBackend* backend = page->heap()->page_backend();
page->heap()->stats_collector()->NotifyFreedMemory(
LargePageAllocationSize(page->PayloadSize()));
backend->FreeLargePageMemory(reinterpret_cast<Address>(page));
}
......
......@@ -29,6 +29,11 @@ class MetricRecorder {
int64_t incremental_sweep_ms;
int64_t concurrent_mark_ms;
int64_t concurrent_sweep_ms;
int64_t objects_before_bytes;
int64_t objects_after_bytes;
int64_t objects_freed_bytes;
int64_t memory_freed_bytes;
};
struct CppGCIncrementalMarkMetricSample {
......
......@@ -93,6 +93,10 @@ void StatsCollector::NotifyMarkingCompleted(size_t marked_bytes) {
DCHECK_EQ(GarbageCollectionState::kMarking, gc_state_);
gc_state_ = GarbageCollectionState::kSweeping;
current_.marked_bytes = marked_bytes;
current_.object_size_before_sweep_bytes =
previous_.marked_bytes + allocated_bytes_since_end_of_marking_ +
allocated_bytes_since_safepoint_ -
explicitly_freed_bytes_since_safepoint_;
allocated_bytes_since_safepoint_ = 0;
explicitly_freed_bytes_since_safepoint_ = 0;
......@@ -104,6 +108,7 @@ void StatsCollector::NotifyMarkingCompleted(size_t marked_bytes) {
// execution of ResetAllocatedObjectSize.
allocated_bytes_since_end_of_marking_ = 0;
time_of_last_end_of_marking_ = v8::base::TimeTicks::Now();
freed_memory_bytes_since_end_of_marking_ = 0;
}
double StatsCollector::GetRecentAllocationSpeedInBytesPerMs() const {
......@@ -128,7 +133,12 @@ void StatsCollector::NotifySweepingCompleted() {
previous_.scope_data[kIncrementalMark].InMilliseconds(),
previous_.scope_data[kIncrementalSweep].InMilliseconds(),
previous_.concurrent_scope_data[kConcurrentMark],
previous_.concurrent_scope_data[kConcurrentSweep]};
previous_.concurrent_scope_data[kConcurrentSweep],
previous_.object_size_before_sweep_bytes /* objects_before */,
previous_.marked_bytes /* objects_after */,
previous_.object_size_before_sweep_bytes -
previous_.marked_bytes /* objects_freed */,
freed_memory_bytes_since_end_of_marking_ /* memory_freed */};
metric_recorder_->AddMainThreadEvent(event);
}
}
......@@ -146,6 +156,10 @@ size_t StatsCollector::allocated_object_size() const {
allocated_bytes_since_end_of_marking_);
}
void StatsCollector::NotifyFreedMemory(int64_t size) {
freed_memory_bytes_since_end_of_marking_ += size;
}
void StatsCollector::RecordHistogramSample(ScopeId scope_id_,
v8::base::TimeDelta time) {
switch (scope_id_) {
......
......@@ -104,6 +104,7 @@ class V8_EXPORT_PRIVATE StatsCollector final {
IsForcedGC is_forced_gc = IsForcedGC::kNotForced;
// Marked bytes collected during marking.
size_t marked_bytes = 0;
size_t object_size_before_sweep_bytes = -1;
};
private:
......@@ -269,6 +270,8 @@ class V8_EXPORT_PRIVATE StatsCollector final {
const Event& GetPreviousEventForTesting() const { return previous_; }
void NotifyFreedMemory(int64_t);
void SetMetricRecorderForTesting(
std::unique_ptr<MetricRecorder> histogram_recorder) {
metric_recorder_ = std::move(histogram_recorder);
......@@ -303,6 +306,8 @@ class V8_EXPORT_PRIVATE StatsCollector final {
int64_t allocated_bytes_since_safepoint_ = 0;
int64_t explicitly_freed_bytes_since_safepoint_ = 0;
int64_t freed_memory_bytes_since_end_of_marking_ = 0;
// vector to allow fast iteration of observers. Register/Unregisters only
// happens on startup/teardown.
std::vector<AllocationObserver*> allocation_observers_;
......
......@@ -134,7 +134,7 @@ TEST_F(MetricRecorderTest, AtomicScopesNotReportedImmediately) {
EndGC(0);
}
TEST_F(MetricRecorderTest, CycleEndHistogramReportedOnGcEnd) {
TEST_F(MetricRecorderTest, CycleEndMetricsReportedOnGcEnd) {
MetricRecorderImpl::CppGCCycleEndMetricSamples_callcount = 0u;
MetricRecorderImpl::CppGCIncrementalMarkMetricSample_callcount = 0u;
MetricRecorderImpl::CppGCIncrementalSweepMetricSample_callcount = 0u;
......@@ -364,5 +364,50 @@ TEST_F(MetricRecorderTest, ConcurrentSamplesAreReported) {
}
}
TEST_F(MetricRecorderTest, ObjectSizeMetricsNoAllocations) {
// Populate previous event.
StartGC();
EndGC(1000);
// Populate current event.
StartGC();
EndGC(800);
EXPECT_EQ(1000u, MetricRecorderImpl::CppGCCycleEndMetricSamples_event
.objects_before_bytes);
EXPECT_EQ(
800u,
MetricRecorderImpl::CppGCCycleEndMetricSamples_event.objects_after_bytes);
EXPECT_EQ(
200u,
MetricRecorderImpl::CppGCCycleEndMetricSamples_event.objects_freed_bytes);
EXPECT_EQ(
0u,
MetricRecorderImpl::CppGCCycleEndMetricSamples_event.memory_freed_bytes);
}
TEST_F(MetricRecorderTest, ObjectSizeMetricsWithAllocations) {
// Populate previous event.
StartGC();
EndGC(1000);
// Populate current event.
StartGC();
stats->NotifyAllocation(300);
stats->NotifyFreedMemory(700);
stats->NotifyMarkingCompleted(800);
stats->NotifyAllocation(150);
stats->NotifyFreedMemory(400);
stats->NotifySweepingCompleted();
EXPECT_EQ(1300u, MetricRecorderImpl::CppGCCycleEndMetricSamples_event
.objects_before_bytes);
EXPECT_EQ(
800,
MetricRecorderImpl::CppGCCycleEndMetricSamples_event.objects_after_bytes);
EXPECT_EQ(
500u,
MetricRecorderImpl::CppGCCycleEndMetricSamples_event.objects_freed_bytes);
EXPECT_EQ(
400u,
MetricRecorderImpl::CppGCCycleEndMetricSamples_event.memory_freed_bytes);
}
} // namespace internal
} // namespace cppgc
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment