Commit 88e5b8f5 authored by Omer Katz's avatar Omer Katz Committed by V8 LUCI CQ

cppgc, heap: Implement UMA reporting for cppgc library.

This CL does 2 things:
1) Implements forwarding of histogram reporting from cppgc to v8 via
CppHeap.
2) Establishes the pipeline in GCTracer for sending the histograms to
the embedder.

Currently only cppgc histograms are populated.

See crrev.com/c/2916956 for usage.

Bug: chromium:1154636
Change-Id: I8150116f757e105d0dfac96a3f6e7dd95717f5bd
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2917033
Commit-Queue: Omer Katz <omerkatz@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#74830}
parent 990c9386
......@@ -8820,7 +8820,7 @@ void Isolate::SetAddHistogramSampleFunction(
void Isolate::SetMetricsRecorder(
const std::shared_ptr<metrics::Recorder>& metrics_recorder) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->metrics_recorder()->SetRecorder(isolate, metrics_recorder);
isolate->metrics_recorder()->SetEmbedderRecorder(isolate, metrics_recorder);
}
void Isolate::SetAddCrashKeyCallback(AddCrashKeyCallback callback) {
......
......@@ -15,8 +15,9 @@
#include "src/base/logging.h"
#include "src/base/macros.h"
#include "src/base/platform/time.h"
#include "src/execution/isolate.h"
#include "src/execution/isolate-inl.h"
#include "src/flags/flags.h"
#include "src/handles/handles.h"
#include "src/heap/base/stack.h"
#include "src/heap/cppgc-js/cpp-snapshot.h"
#include "src/heap/cppgc-js/unified-heap-marking-state.h"
......@@ -29,15 +30,18 @@
#include "src/heap/cppgc/marker.h"
#include "src/heap/cppgc/marking-state.h"
#include "src/heap/cppgc/marking-visitor.h"
#include "src/heap/cppgc/metric-recorder.h"
#include "src/heap/cppgc/object-allocator.h"
#include "src/heap/cppgc/prefinalizer-handler.h"
#include "src/heap/cppgc/raw-heap.h"
#include "src/heap/cppgc/stats-collector.h"
#include "src/heap/cppgc/sweeper.h"
#include "src/heap/embedder-tracing.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/marking-worklist.h"
#include "src/heap/sweeper.h"
#include "src/init/v8.h"
#include "src/logging/metrics.h"
#include "src/profiler/heap-profiler.h"
namespace v8 {
......@@ -215,16 +219,74 @@ void UnifiedHeapMarker::AddObject(void* object) {
} // namespace
class CppHeap::MetricRecorderAdapter final
: public cppgc::internal::MetricRecorder {
public:
explicit MetricRecorderAdapter(CppHeap& cpp_heap) : cpp_heap_(cpp_heap) {}
void AddMainThreadEvent(const FullCycle& cppgc_event) final {
cpp_heap_.last_cppgc_full_gc_event_ = cppgc_event;
GetIsolate()->heap()->tracer()->NotifyGCCompleted();
}
void AddMainThreadEvent(const MainThreadIncrementalMark& cppgc_event) final {
// Incremental marking steps might be nested in V8 marking steps. In such
// cases, stash the relevant values and delegate to V8 to report them. For
// non-nested steps, report to the Recorder directly.
if (cpp_heap_.is_in_v8_marking_step_) {
cpp_heap_.last_cppgc_incremental_mark_event_ = cppgc_event;
return;
}
// This is a standalone incremental marking step.
const std::shared_ptr<metrics::Recorder>& recorder =
GetIsolate()->metrics_recorder();
DCHECK_NOT_NULL(recorder);
if (!recorder->HasEmbedderRecorder()) return;
::v8::metrics::GarbageCollectionFullMainThreadIncrementalMark event;
event.cpp_wall_clock_duration_in_us = cppgc_event.duration_us;
// TODO(chromium:1154636): Populate event.wall_clock_duration_in_us.
recorder->AddMainThreadEvent(event, GetContextId());
}
void AddMainThreadEvent(const MainThreadIncrementalSweep& cppgc_event) final {
// Incremental sweeping steps are never nested inside V8 sweeping steps, so
// report to the Recorder directly.
const std::shared_ptr<metrics::Recorder>& recorder =
GetIsolate()->metrics_recorder();
DCHECK_NOT_NULL(recorder);
if (!recorder->HasEmbedderRecorder()) return;
::v8::metrics::GarbageCollectionFullMainThreadIncrementalSweep event;
event.cpp_wall_clock_duration_in_us = cppgc_event.duration_us;
// TODO(chromium:1154636): Populate event.wall_clock_duration_in_us.
recorder->AddMainThreadEvent(event, GetContextId());
}
private:
Isolate* GetIsolate() {
DCHECK_NOT_NULL(cpp_heap_.isolate());
return reinterpret_cast<Isolate*>(cpp_heap_.isolate());
}
v8::metrics::Recorder::ContextId GetContextId() {
DCHECK_NOT_NULL(GetIsolate());
if (GetIsolate()->context().is_null())
return v8::metrics::Recorder::ContextId::Empty();
HandleScope scope(GetIsolate());
return GetIsolate()->GetOrRegisterRecorderContextId(
GetIsolate()->native_context());
}
CppHeap& cpp_heap_;
};
CppHeap::CppHeap(
v8::Platform* platform,
const std::vector<std::unique_ptr<cppgc::CustomSpaceBase>>& custom_spaces,
const v8::WrapperDescriptor& wrapper_descriptor,
std::unique_ptr<cppgc::internal::MetricRecorder> metric_recorder)
const v8::WrapperDescriptor& wrapper_descriptor)
: cppgc::internal::HeapBase(
std::make_shared<CppgcPlatformAdapter>(platform), custom_spaces,
cppgc::internal::HeapBase::StackSupport::
kSupportsConservativeStackScan,
std::move(metric_recorder)),
kSupportsConservativeStackScan),
wrapper_descriptor_(wrapper_descriptor) {
CHECK_NE(WrapperDescriptor::kUnknownEmbedderId,
wrapper_descriptor_.embedder_id_for_garbage_collected);
......@@ -260,6 +322,7 @@ void CppHeap::AttachIsolate(Isolate* isolate) {
isolate_->heap()->SetEmbedderHeapTracer(this);
isolate_->heap()->local_embedder_heap_tracer()->SetWrapperDescriptor(
wrapper_descriptor_);
SetMetricRecorder(std::make_unique<MetricRecorderAdapter>(*this));
no_gc_scope_--;
}
......@@ -277,6 +340,7 @@ void CppHeap::DetachIsolate() {
isolate_->heap_profiler()->RemoveBuildEmbedderGraphCallback(
&CppGraphBuilder::Run, this);
}
SetMetricRecorder(nullptr);
isolate_ = nullptr;
// Any future garbage collections will ignore the V8->C++ references.
isolate()->SetEmbedderHeapTracer(nullptr);
......@@ -328,6 +392,7 @@ void CppHeap::TracePrologue(TraceFlags flags) {
}
bool CppHeap::AdvanceTracing(double deadline_in_ms) {
is_in_v8_marking_step_ = true;
cppgc::internal::StatsCollector::EnabledScope stats_scope(
stats_collector(),
in_atomic_pause_ ? cppgc::internal::StatsCollector::kAtomicMark
......@@ -341,6 +406,7 @@ bool CppHeap::AdvanceTracing(double deadline_in_ms) {
marking_done_ =
marker_->AdvanceMarkingWithLimits(deadline, marked_bytes_limit);
DCHECK_IMPLIES(in_atomic_pause_, marking_done_);
is_in_v8_marking_step_ = false;
return marking_done_;
}
......
......@@ -39,9 +39,7 @@ class V8_EXPORT_PRIVATE CppHeap final
CppHeap(
v8::Platform* platform,
const std::vector<std::unique_ptr<cppgc::CustomSpaceBase>>& custom_spaces,
const v8::WrapperDescriptor& wrapper_descriptor,
std::unique_ptr<cppgc::internal::MetricRecorder> metric_recorder =
nullptr);
const v8::WrapperDescriptor& wrapper_descriptor);
~CppHeap() final;
CppHeap(const CppHeap&) = delete;
......@@ -78,7 +76,24 @@ class V8_EXPORT_PRIVATE CppHeap final
void AllocatedObjectSizeDecreased(size_t) final;
void ResetAllocatedObjectSize(size_t) final {}
// The following 3 methods are only used for reporting nested cpp events
// through V8. Standalone events are reported directly.
bool MetricsReportPending() const {
return last_cppgc_full_gc_event_.has_value();
}
const base::Optional<cppgc::internal::MetricRecorder::FullCycle>
ExtractLastCppgcFullGcEvent() {
return std::move(last_cppgc_full_gc_event_);
}
const base::Optional<
cppgc::internal::MetricRecorder::MainThreadIncrementalMark>
ExtractLastCppgcIncrementalMarkEvent() {
return std::move(last_cppgc_incremental_mark_event_);
}
private:
class MetricRecorderAdapter;
void FinalizeIncrementalGarbageCollectionIfNeeded(
cppgc::Heap::StackState) final {
// For unified heap, CppHeap shouldn't finalize independently (i.e.
......@@ -103,6 +118,14 @@ class V8_EXPORT_PRIVATE CppHeap final
bool in_detached_testing_mode_ = false;
bool force_incremental_marking_for_testing_ = false;
bool is_in_v8_marking_step_ = false;
base::Optional<cppgc::internal::MetricRecorder::FullCycle>
last_cppgc_full_gc_event_;
base::Optional<cppgc::internal::MetricRecorder::MainThreadIncrementalMark>
last_cppgc_incremental_mark_event_;
friend class MetricRecorderAdapter;
};
} // namespace internal
......
......@@ -53,8 +53,7 @@ class ObjectSizeCounter : private HeapVisitor<ObjectSizeCounter> {
HeapBase::HeapBase(
std::shared_ptr<cppgc::Platform> platform,
const std::vector<std::unique_ptr<CustomSpaceBase>>& custom_spaces,
StackSupport stack_support,
std::unique_ptr<MetricRecorder> histogram_recorder)
StackSupport stack_support)
: raw_heap_(this, custom_spaces),
platform_(std::move(platform)),
#if defined(LEAK_SANITIZER)
......@@ -67,8 +66,7 @@ HeapBase::HeapBase(
#else // !CPPGC_CAGED_HEAP
page_backend_(std::make_unique<PageBackend>(page_allocator())),
#endif // !CPPGC_CAGED_HEAP
stats_collector_(std::make_unique<StatsCollector>(
std::move(histogram_recorder), platform_.get())),
stats_collector_(std::make_unique<StatsCollector>(platform_.get())),
stack_(std::make_unique<heap::base::Stack>(
v8::base::Stack::GetStackStart())),
prefinalizer_handler_(std::make_unique<PreFinalizerHandler>(*this)),
......
......@@ -83,8 +83,7 @@ class V8_EXPORT_PRIVATE HeapBase : public cppgc::HeapHandle {
HeapBase(std::shared_ptr<cppgc::Platform> platform,
const std::vector<std::unique_ptr<CustomSpaceBase>>& custom_spaces,
StackSupport stack_support,
std::unique_ptr<MetricRecorder> histogram_recorder);
StackSupport stack_support);
virtual ~HeapBase();
HeapBase(const HeapBase&) = delete;
......@@ -196,6 +195,10 @@ class V8_EXPORT_PRIVATE HeapBase : public cppgc::HeapHandle {
virtual void FinalizeIncrementalGarbageCollectionForTesting(
EmbedderStackState) = 0;
void SetMetricRecorder(std::unique_ptr<MetricRecorder> histogram_recorder) {
stats_collector_->SetMetricRecorder(std::move(histogram_recorder));
}
protected:
// Used by the incremental scheduler to finalize a GC if supported.
virtual void FinalizeIncrementalGarbageCollectionIfNeeded(
......
......@@ -87,8 +87,7 @@ void CheckConfig(Heap::Config config, Heap::MarkingType marking_support,
Heap::Heap(std::shared_ptr<cppgc::Platform> platform,
cppgc::Heap::HeapOptions options)
: HeapBase(platform, options.custom_spaces, options.stack_support,
nullptr /* metric_recorder */),
: HeapBase(platform, options.custom_spaces, options.stack_support),
gc_invoker_(this, platform_.get(), options.stack_support),
growing_(&gc_invoker_, stats_collector_.get(),
options.resource_constraints, options.marking_support,
......
......@@ -20,19 +20,19 @@ class StatsCollector;
*/
class MetricRecorder {
public:
struct CppGCFullCycle {
struct FullCycle {
struct IncrementalPhases {
int64_t mark_duration_us;
int64_t sweep_duration_us;
int64_t mark_duration_us = -1;
int64_t sweep_duration_us = -1;
};
struct Phases : public IncrementalPhases {
int64_t weak_duration_us;
int64_t compact_duration_us;
int64_t weak_duration_us = -1;
int64_t compact_duration_us = -1;
};
struct Sizes {
int64_t before_bytes;
int64_t after_bytes;
int64_t freed_bytes;
int64_t before_bytes = -1;
int64_t after_bytes = -1;
int64_t freed_bytes = -1;
};
Phases total;
......@@ -46,21 +46,19 @@ class MetricRecorder {
double main_thread_efficiency_in_bytes_per_us;
};
struct CppGCMainThreadIncrementalMark {
int64_t duration_us;
struct MainThreadIncrementalMark {
int64_t duration_us = -1;
};
struct CppGCMainThreadIncrementalSweep {
int64_t duration_us;
struct MainThreadIncrementalSweep {
int64_t duration_us = -1;
};
virtual ~MetricRecorder() = default;
virtual void AddMainThreadEvent(const CppGCFullCycle& event) {}
virtual void AddMainThreadEvent(const CppGCMainThreadIncrementalMark& event) {
}
virtual void AddMainThreadEvent(
const CppGCMainThreadIncrementalSweep& event) {}
virtual void AddMainThreadEvent(const FullCycle& event) {}
virtual void AddMainThreadEvent(const MainThreadIncrementalMark& event) {}
virtual void AddMainThreadEvent(const MainThreadIncrementalSweep& event) {}
};
} // namespace internal
......
......@@ -18,9 +18,7 @@ namespace internal {
// static
constexpr size_t StatsCollector::kAllocationThresholdBytes;
StatsCollector::StatsCollector(
std::unique_ptr<MetricRecorder> histogram_recorder, Platform* platform)
: metric_recorder_(std::move(histogram_recorder)), platform_(platform) {
StatsCollector::StatsCollector(Platform* platform) : platform_(platform) {
USE(platform_);
}
......@@ -154,12 +152,12 @@ double StatsCollector::GetRecentAllocationSpeedInBytesPerMs() const {
namespace {
int64_t SumPhases(const MetricRecorder::CppGCFullCycle::Phases& phases) {
int64_t SumPhases(const MetricRecorder::FullCycle::Phases& phases) {
return phases.mark_duration_us + phases.weak_duration_us +
phases.compact_duration_us + phases.sweep_duration_us;
}
MetricRecorder::CppGCFullCycle GetFullCycleEventForMetricRecorder(
MetricRecorder::FullCycle GetFullCycleEventForMetricRecorder(
int64_t atomic_mark_us, int64_t atomic_weak_us, int64_t atomic_compact_us,
int64_t atomic_sweep_us, int64_t incremental_mark_us,
int64_t incremental_sweep_us, int64_t concurrent_mark_us,
......@@ -167,7 +165,7 @@ MetricRecorder::CppGCFullCycle GetFullCycleEventForMetricRecorder(
int64_t objects_after_bytes, int64_t objects_freed_bytes,
int64_t memory_before_bytes, int64_t memory_after_bytes,
int64_t memory_freed_bytes) {
MetricRecorder::CppGCFullCycle event;
MetricRecorder::FullCycle event;
// MainThread.Incremental:
event.main_thread_incremental.mark_duration_us = incremental_mark_us;
event.main_thread_incremental.sweep_duration_us = incremental_sweep_us;
......@@ -223,7 +221,7 @@ void StatsCollector::NotifySweepingCompleted() {
previous_ = std::move(current_);
current_ = Event();
if (metric_recorder_) {
MetricRecorder::CppGCFullCycle event = GetFullCycleEventForMetricRecorder(
MetricRecorder::FullCycle event = GetFullCycleEventForMetricRecorder(
previous_.scope_data[kAtomicMark].InMicroseconds(),
previous_.scope_data[kAtomicWeak].InMicroseconds(),
previous_.scope_data[kAtomicCompact].InMicroseconds(),
......@@ -315,14 +313,12 @@ void StatsCollector::RecordHistogramSample(ScopeId scope_id_,
v8::base::TimeDelta time) {
switch (scope_id_) {
case kIncrementalMark: {
MetricRecorder::CppGCMainThreadIncrementalMark event{
time.InMicroseconds()};
MetricRecorder::MainThreadIncrementalMark event{time.InMicroseconds()};
metric_recorder_->AddMainThreadEvent(event);
break;
}
case kIncrementalSweep: {
MetricRecorder::CppGCMainThreadIncrementalSweep event{
time.InMicroseconds()};
MetricRecorder::MainThreadIncrementalSweep event{time.InMicroseconds()};
metric_recorder_->AddMainThreadEvent(event);
break;
}
......
......@@ -249,7 +249,7 @@ class V8_EXPORT_PRIVATE StatsCollector final {
// reasonably interesting sizes.
static constexpr size_t kAllocationThresholdBytes = 1024;
StatsCollector(std::unique_ptr<MetricRecorder>, Platform*);
explicit StatsCollector(Platform*);
StatsCollector(const StatsCollector&) = delete;
StatsCollector& operator=(const StatsCollector&) = delete;
......@@ -293,8 +293,7 @@ class V8_EXPORT_PRIVATE StatsCollector final {
void NotifyAllocatedMemory(int64_t);
void NotifyFreedMemory(int64_t);
void SetMetricRecorderForTesting(
std::unique_ptr<MetricRecorder> histogram_recorder) {
void SetMetricRecorder(std::unique_ptr<MetricRecorder> histogram_recorder) {
metric_recorder_ = std::move(histogram_recorder);
}
......@@ -347,6 +346,7 @@ class V8_EXPORT_PRIVATE StatsCollector final {
std::unique_ptr<MetricRecorder> metric_recorder_;
// |platform_| is used by the TRACE_EVENT_* macros.
Platform* platform_;
};
......
......@@ -6,14 +6,18 @@
#include <cstdarg>
#include "include/v8-metrics.h"
#include "src/base/atomic-utils.h"
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/execution/thread-id.h"
#include "src/heap/cppgc-js/cpp-heap.h"
#include "src/heap/cppgc/metric-recorder.h"
#include "src/heap/heap-inl.h"
#include "src/heap/incremental-marking.h"
#include "src/heap/spaces.h"
#include "src/logging/counters.h"
#include "src/logging/metrics.h"
#include "src/logging/tracing-flags.h"
#include "src/tracing/tracing-category-observer.h"
......@@ -445,6 +449,8 @@ void GCTracer::NotifySweepingCompleted() {
heap_->code_space()->PrintAllocationsOrigins();
heap_->map_space()->PrintAllocationsOrigins();
}
metrics_report_pending_ = true;
NotifyGCCompleted();
}
void GCTracer::SampleAllocation(double current_ms,
......@@ -513,6 +519,7 @@ void GCTracer::AddIncrementalMarkingStep(double duration, size_t bytes) {
incremental_marking_bytes_ += bytes;
incremental_marking_duration_ += duration;
}
ReportIncrementalMarkingStepToRecorder();
}
void GCTracer::Output(const char* format, ...) const {
......@@ -1295,5 +1302,123 @@ void GCTracer::RecordGCSumCounters(double atomic_pause_duration) {
"background_duration", marking_background_duration);
}
void GCTracer::NotifyGCCompleted() {
// Report full GC cycle metric to recorder only when both v8 and cppgc (if
// available) GCs have finished. This method is invoked by both v8 and cppgc.
if (!metrics_report_pending_) {
// V8 sweeping is not done yet.
return;
}
const auto* cpp_heap = heap_->cpp_heap();
if (cpp_heap && !CppHeap::From(cpp_heap)->MetricsReportPending()) {
// Cppgc sweeping is not done yet.
return;
}
ReportFullCycleToRecorder();
}
namespace {
void CopyTimeMetrics(
::v8::metrics::GarbageCollectionPhases& metrics,
const cppgc::internal::MetricRecorder::FullCycle::IncrementalPhases&
cppgc_metrics) {
DCHECK_NE(-1, cppgc_metrics.mark_duration_us);
metrics.mark_wall_clock_duration_in_us = cppgc_metrics.mark_duration_us;
DCHECK_NE(-1, cppgc_metrics.sweep_duration_us);
metrics.sweep_wall_clock_duration_in_us = cppgc_metrics.sweep_duration_us;
}
void CopyTimeMetrics(
::v8::metrics::GarbageCollectionPhases& metrics,
const cppgc::internal::MetricRecorder::FullCycle::Phases& cppgc_metrics) {
DCHECK_NE(-1, cppgc_metrics.compact_duration_us);
metrics.compact_wall_clock_duration_in_us = cppgc_metrics.compact_duration_us;
DCHECK_NE(-1, cppgc_metrics.mark_duration_us);
metrics.mark_wall_clock_duration_in_us = cppgc_metrics.mark_duration_us;
DCHECK_NE(-1, cppgc_metrics.sweep_duration_us);
metrics.sweep_wall_clock_duration_in_us = cppgc_metrics.sweep_duration_us;
DCHECK_NE(-1, cppgc_metrics.weak_duration_us);
metrics.weak_wall_clock_duration_in_us = cppgc_metrics.weak_duration_us;
}
void CopySizeMetrics(
::v8::metrics::GarbageCollectionSizes& metrics,
const cppgc::internal::MetricRecorder::FullCycle::Sizes& cppgc_metrics) {
DCHECK_NE(-1, cppgc_metrics.after_bytes);
metrics.bytes_after = cppgc_metrics.after_bytes;
DCHECK_NE(-1, cppgc_metrics.before_bytes);
metrics.bytes_before = cppgc_metrics.before_bytes;
DCHECK_NE(-1, cppgc_metrics.freed_bytes);
metrics.bytes_freed = cppgc_metrics.freed_bytes;
}
::v8::metrics::Recorder::ContextId GetContextId(
v8::internal::Isolate* isolate) {
DCHECK_NOT_NULL(isolate);
if (isolate->context().is_null())
return v8::metrics::Recorder::ContextId::Empty();
HandleScope scope(isolate);
return isolate->GetOrRegisterRecorderContextId(isolate->native_context());
}
} // namespace
void GCTracer::ReportFullCycleToRecorder() {
const std::shared_ptr<metrics::Recorder>& recorder =
heap_->isolate()->metrics_recorder();
DCHECK_NOT_NULL(recorder);
if (!recorder->HasEmbedderRecorder()) return;
::v8::metrics::GarbageCollectionFullCycle event;
if (heap_->cpp_heap()) {
const base::Optional<cppgc::internal::MetricRecorder::FullCycle>
optional_cppgc_event = v8::internal::CppHeap::From(heap_->cpp_heap())
->ExtractLastCppgcFullGcEvent();
DCHECK(optional_cppgc_event.has_value());
const cppgc::internal::MetricRecorder::FullCycle& cppgc_event =
optional_cppgc_event.value();
CopyTimeMetrics(event.total_cpp, cppgc_event.total);
CopyTimeMetrics(event.main_thread_cpp, cppgc_event.main_thread);
CopyTimeMetrics(event.main_thread_atomic_cpp,
cppgc_event.main_thread_atomic);
CopyTimeMetrics(event.main_thread_incremental_cpp,
cppgc_event.main_thread_incremental);
CopySizeMetrics(event.objects_cpp, cppgc_event.objects);
CopySizeMetrics(event.memory_cpp, cppgc_event.memory);
DCHECK_NE(-1, cppgc_event.collection_rate_in_percent);
event.collection_rate_cpp_in_percent =
cppgc_event.collection_rate_in_percent;
DCHECK_NE(-1, cppgc_event.efficiency_in_bytes_per_us);
event.efficiency_cpp_in_bytes_per_us =
cppgc_event.efficiency_in_bytes_per_us;
DCHECK_NE(-1, cppgc_event.main_thread_efficiency_in_bytes_per_us);
event.main_thread_efficiency_cpp_in_bytes_per_us =
cppgc_event.main_thread_efficiency_in_bytes_per_us;
}
// TODO(chromium:1154636): Populate v8 metrics.
recorder->AddMainThreadEvent(event, GetContextId(heap_->isolate()));
metrics_report_pending_ = false;
}
void GCTracer::ReportIncrementalMarkingStepToRecorder() {
const std::shared_ptr<metrics::Recorder>& recorder =
heap_->isolate()->metrics_recorder();
DCHECK_NOT_NULL(recorder);
if (!recorder->HasEmbedderRecorder()) return;
::v8::metrics::GarbageCollectionFullMainThreadIncrementalMark event;
if (heap_->cpp_heap()) {
const base::Optional<
cppgc::internal::MetricRecorder::MainThreadIncrementalMark>
cppgc_event = v8::internal::CppHeap::From(heap_->cpp_heap())
->ExtractLastCppgcIncrementalMarkEvent();
if (cppgc_event.has_value()) {
DCHECK_NE(-1, cppgc_event.value().duration_us);
event.cpp_wall_clock_duration_in_us = cppgc_event.value().duration_us;
}
}
// TODO(chromium:1154636): Populate event.wall_clock_duration_in_us.
recorder->AddMainThreadEvent(event, GetContextId(heap_->isolate()));
}
} // namespace internal
} // namespace v8
......@@ -214,6 +214,8 @@ class V8_EXPORT_PRIVATE GCTracer {
void NotifySweepingCompleted();
void NotifyGCCompleted();
void NotifyYoungGenerationHandling(
YoungGenerationHandling young_generation_handling);
......@@ -414,6 +416,9 @@ class V8_EXPORT_PRIVATE GCTracer {
void FetchBackgroundMarkCompactCounters();
void FetchBackgroundGeneralCounters();
void ReportFullCycleToRecorder();
void ReportIncrementalMarkingStepToRecorder();
// Pointer to the heap that owns this tracer.
Heap* heap_;
......@@ -479,6 +484,8 @@ class V8_EXPORT_PRIVATE GCTracer {
base::RingBuffer<BytesAndDuration> recorded_embedder_generation_allocations_;
base::RingBuffer<double> recorded_survival_ratios_;
bool metrics_report_pending_ = false;
base::Mutex background_counter_mutex_;
BackgroundCounter background_counter_[Scope::NUMBER_OF_SCOPES];
};
......
......@@ -31,7 +31,7 @@ class Recorder::Task : public v8::Task {
std::shared_ptr<Recorder> recorder_;
};
void Recorder::SetRecorder(
void Recorder::SetEmbedderRecorder(
Isolate* isolate,
const std::shared_ptr<v8::metrics::Recorder>& embedder_recorder) {
foreground_task_runner_ = V8::GetCurrentPlatform()->GetForegroundTaskRunner(
......@@ -40,6 +40,8 @@ void Recorder::SetRecorder(
embedder_recorder_ = embedder_recorder;
}
bool Recorder::HasEmbedderRecorder() const { return embedder_recorder_.get(); }
void Recorder::NotifyIsolateDisposal() {
if (embedder_recorder_) {
embedder_recorder_->NotifyIsolateDisposal();
......
......@@ -22,10 +22,12 @@ namespace metrics {
class Recorder : public std::enable_shared_from_this<Recorder> {
public:
V8_EXPORT_PRIVATE void SetRecorder(
V8_EXPORT_PRIVATE void SetEmbedderRecorder(
Isolate* isolate,
const std::shared_ptr<v8::metrics::Recorder>& embedder_recorder);
V8_EXPORT_PRIVATE bool HasEmbedderRecorder() const;
V8_EXPORT_PRIVATE void NotifyIsolateDisposal();
template <class T>
......
......@@ -57,11 +57,12 @@ void FakeAllocate(StatsCollector* stats_collector, size_t bytes) {
stats_collector->NotifySafePointForConservativeCollection();
}
static constexpr Platform* kNoPlatform = nullptr;
} // namespace
TEST(HeapGrowingTest, ConservativeGCInvoked) {
StatsCollector stats_collector(nullptr /* metric_recorder */,
nullptr /* platform */);
StatsCollector stats_collector(kNoPlatform);
MockGarbageCollector gc;
cppgc::Heap::ResourceConstraints constraints;
// Force GC at the first update.
......@@ -77,8 +78,7 @@ TEST(HeapGrowingTest, ConservativeGCInvoked) {
}
TEST(HeapGrowingTest, InitialHeapSize) {
StatsCollector stats_collector(nullptr /* metric_recorder */,
nullptr /* platform */);
StatsCollector stats_collector(kNoPlatform);
MockGarbageCollector gc;
cppgc::Heap::ResourceConstraints constraints;
// Use larger size to avoid running into small heap optimizations.
......@@ -98,8 +98,7 @@ TEST(HeapGrowingTest, InitialHeapSize) {
TEST(HeapGrowingTest, ConstantGrowingFactor) {
// Use larger size to avoid running into small heap optimizations.
constexpr size_t kObjectSize = 10 * HeapGrowing::kMinLimitIncrease;
StatsCollector stats_collector(nullptr /* metric_recorder */,
nullptr /* platform */);
StatsCollector stats_collector(kNoPlatform);
FakeGarbageCollector gc(&stats_collector);
cppgc::Heap::ResourceConstraints constraints;
// Force GC at the first update.
......@@ -117,8 +116,7 @@ TEST(HeapGrowingTest, ConstantGrowingFactor) {
TEST(HeapGrowingTest, SmallHeapGrowing) {
// Larger constant to avoid running into special handling for smaller heaps.
constexpr size_t kLargeAllocation = 100 * kMB;
StatsCollector stats_collector(nullptr /* metric_recorder */,
nullptr /* platform */);
StatsCollector stats_collector(kNoPlatform);
FakeGarbageCollector gc(&stats_collector);
cppgc::Heap::ResourceConstraints constraints;
// Force GC at the first update.
......@@ -134,8 +132,7 @@ TEST(HeapGrowingTest, SmallHeapGrowing) {
}
TEST(HeapGrowingTest, IncrementalGCStarted) {
StatsCollector stats_collector(nullptr /* metric_recorder */,
nullptr /* platform */);
StatsCollector stats_collector(kNoPlatform);
MockGarbageCollector gc;
cppgc::Heap::ResourceConstraints constraints;
HeapGrowing growing(&gc, &stats_collector, constraints,
......@@ -152,8 +149,7 @@ TEST(HeapGrowingTest, IncrementalGCStarted) {
}
TEST(HeapGrowingTest, IncrementalGCFinalized) {
StatsCollector stats_collector(nullptr /* metric_recorder */,
nullptr /* platform */);
StatsCollector stats_collector(kNoPlatform);
MockGarbageCollector gc;
cppgc::Heap::ResourceConstraints constraints;
HeapGrowing growing(&gc, &stats_collector, constraints,
......
......@@ -18,8 +18,9 @@ constexpr size_t kMinReportedSize = StatsCollector::kAllocationThresholdBytes;
class StatsCollectorTest : public ::testing::Test {
public:
StatsCollectorTest()
: stats(nullptr /* metric_recorder */, nullptr /* platform */) {}
static constexpr Platform* kNoPlatform = nullptr;
StatsCollectorTest() : stats(kNoPlatform) {}
void FakeAllocate(size_t bytes) {
stats.NotifyAllocation(bytes);
......
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