Commit fd554885 authored by Ulan Degenbaev's avatar Ulan Degenbaev Committed by Commit Bot

[heap] Add background GC tracing infrastructure.

A background task can now use GCTracer::BackgroundScope to
trace the time spent in the task. The time shows up in
--trace-gc-nvp output and in the runtime call stats for GC.

The destructor of GCTracer::BackgroundScope increments the
corresponding counter in heap()->tracer()->background_counter_,
which is protected by a mutex.

The GCTracer::Stop function fetches background_counter_ items
into the global scope and into the runtime call stats.

Bug: chromium:758183
Change-Id: Id7bcd5089ba6c027fe9a57eb3f7db1cb5092aec5
Reviewed-on: https://chromium-review.googlesource.com/801694
Commit-Queue: Ulan Degenbaev <ulan@chromium.org>
Reviewed-by: 's avatarCamillo Bruni <cbruni@chromium.org>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49841}
parent e4c97c82
...@@ -579,6 +579,7 @@ double AggregatedMemoryHistogram<Histogram>::Aggregate(double current_ms, ...@@ -579,6 +579,7 @@ double AggregatedMemoryHistogram<Histogram>::Aggregate(double current_ms,
class RuntimeCallCounter final { class RuntimeCallCounter final {
public: public:
RuntimeCallCounter() : RuntimeCallCounter(nullptr) {}
explicit RuntimeCallCounter(const char* name) explicit RuntimeCallCounter(const char* name)
: name_(name), count_(0), time_(0) {} : name_(name), count_(0), time_(0) {}
V8_NOINLINE void Reset(); V8_NOINLINE void Reset();
...@@ -596,8 +597,6 @@ class RuntimeCallCounter final { ...@@ -596,8 +597,6 @@ class RuntimeCallCounter final {
private: private:
friend class RuntimeCallStats; friend class RuntimeCallStats;
RuntimeCallCounter() {}
const char* name_; const char* name_;
int64_t count_; int64_t count_;
// Stored as int64_t so that its initialization can be deferred. // Stored as int64_t so that its initialization can be deferred.
...@@ -634,7 +633,9 @@ class RuntimeCallTimer final { ...@@ -634,7 +633,9 @@ class RuntimeCallTimer final {
base::TimeDelta elapsed_; base::TimeDelta elapsed_;
}; };
#define FOR_EACH_GC_COUNTER(V) TRACER_SCOPES(V) #define FOR_EACH_GC_COUNTER(V) \
TRACER_SCOPES(V) \
TRACER_BACKGROUND_SCOPES(V)
#define FOR_EACH_API_COUNTER(V) \ #define FOR_EACH_API_COUNTER(V) \
V(ArrayBuffer_Cast) \ V(ArrayBuffer_Cast) \
......
...@@ -356,4 +356,14 @@ ...@@ -356,4 +356,14 @@
F(SCAVENGER_SCAVENGE_ROOTS) \ F(SCAVENGER_SCAVENGE_ROOTS) \
F(SCAVENGER_SCAVENGE_WEAK) F(SCAVENGER_SCAVENGE_WEAK)
#define TRACER_BACKGROUND_SCOPES(F) \
F(SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL) \
F(MINOR_MC_BACKGROUND_MARKING) \
F(MINOR_MC_BACKGROUND_EVACUATE_COPY) \
F(MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS) \
F(MC_BACKGROUND_MARKING) \
F(MC_BACKGROUND_SWEEPING) \
F(MC_BACKGROUND_EVACUATE_COPY) \
F(MC_BACKGROUND_EVACUATE_UPDATE_POINTERS)
#endif // V8_HEAP_SYMBOLS_H_ #endif // V8_HEAP_SYMBOLS_H_
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <stack> #include <stack>
#include <unordered_map> #include <unordered_map>
#include "src/heap/gc-tracer.h"
#include "src/heap/heap-inl.h" #include "src/heap/heap-inl.h"
#include "src/heap/heap.h" #include "src/heap/heap.h"
#include "src/heap/mark-compact-inl.h" #include "src/heap/mark-compact-inl.h"
...@@ -427,6 +428,7 @@ ConcurrentMarking::ConcurrentMarking(Heap* heap, MarkingWorklist* shared, ...@@ -427,6 +428,7 @@ ConcurrentMarking::ConcurrentMarking(Heap* heap, MarkingWorklist* shared,
} }
void ConcurrentMarking::Run(int task_id, TaskState* task_state) { void ConcurrentMarking::Run(int task_id, TaskState* task_state) {
// TODO(ulan): add GCTracer background scope.
size_t kBytesUntilInterruptCheck = 64 * KB; size_t kBytesUntilInterruptCheck = 64 * KB;
int kObjectsUntilInterrupCheck = 1000; int kObjectsUntilInterrupCheck = 1000;
LiveBytesMap* live_bytes = nullptr; LiveBytesMap* live_bytes = nullptr;
......
...@@ -48,12 +48,34 @@ GCTracer::Scope::~Scope() { ...@@ -48,12 +48,34 @@ GCTracer::Scope::~Scope() {
runtime_stats_->Leave(&timer_); runtime_stats_->Leave(&timer_);
} }
GCTracer::BackgroundScope::BackgroundScope(GCTracer* tracer, ScopeId scope)
: tracer_(tracer), scope_(scope), runtime_stats_enabled_(false) {
start_time_ = tracer_->heap_->MonotonicallyIncreasingTimeInMs();
// TODO(cbruni): remove once we fully moved to a trace-based system.
if (V8_LIKELY(!FLAG_runtime_stats)) return;
timer_.Start(&counter_, nullptr);
runtime_stats_enabled_ = true;
}
GCTracer::BackgroundScope::~BackgroundScope() {
double duration_ms =
tracer_->heap_->MonotonicallyIncreasingTimeInMs() - start_time_;
// TODO(cbruni): remove once we fully moved to a trace-based system.
if (V8_LIKELY(!runtime_stats_enabled_)) {
tracer_->AddBackgroundScopeSample(scope_, duration_ms, nullptr);
} else {
timer_.Stop();
tracer_->AddBackgroundScopeSample(scope_, duration_ms, &counter_);
}
}
const char* GCTracer::Scope::Name(ScopeId id) { const char* GCTracer::Scope::Name(ScopeId id) {
#define CASE(scope) \ #define CASE(scope) \
case Scope::scope: \ case Scope::scope: \
return "V8.GC_" #scope; return "V8.GC_" #scope;
switch (id) { switch (id) {
TRACER_SCOPES(CASE) TRACER_SCOPES(CASE)
TRACER_BACKGROUND_SCOPES(CASE)
case Scope::NUMBER_OF_SCOPES: case Scope::NUMBER_OF_SCOPES:
break; break;
} }
...@@ -122,6 +144,10 @@ GCTracer::GCTracer(Heap* heap) ...@@ -122,6 +144,10 @@ GCTracer::GCTracer(Heap* heap)
// map it to RuntimeCallStats. // map it to RuntimeCallStats.
STATIC_ASSERT(0 == Scope::MC_INCREMENTAL); STATIC_ASSERT(0 == Scope::MC_INCREMENTAL);
current_.end_time = heap_->MonotonicallyIncreasingTimeInMs(); current_.end_time = heap_->MonotonicallyIncreasingTimeInMs();
for (int i = 0; i < BackgroundScope::NUMBER_OF_SCOPES; i++) {
background_counter_[i].total_duration_ms = 0;
background_counter_[i].runtime_call_counter = RuntimeCallCounter(nullptr);
}
} }
void GCTracer::ResetForTesting() { void GCTracer::ResetForTesting() {
...@@ -146,6 +172,10 @@ void GCTracer::ResetForTesting() { ...@@ -146,6 +172,10 @@ void GCTracer::ResetForTesting() {
recorded_context_disposal_times_.Reset(); recorded_context_disposal_times_.Reset();
recorded_survival_ratios_.Reset(); recorded_survival_ratios_.Reset();
start_counter_ = 0; start_counter_ = 0;
for (int i = 0; i < BackgroundScope::NUMBER_OF_SCOPES; i++) {
background_counter_[i].total_duration_ms = 0;
background_counter_[i].runtime_call_counter.Reset();
}
} }
void GCTracer::NotifyYoungGenerationHandling( void GCTracer::NotifyYoungGenerationHandling(
...@@ -266,6 +296,7 @@ void GCTracer::Stop(GarbageCollector collector) { ...@@ -266,6 +296,7 @@ void GCTracer::Stop(GarbageCollector collector) {
MakeBytesAndDuration(current_.new_space_object_size, duration)); MakeBytesAndDuration(current_.new_space_object_size, duration));
recorded_minor_gcs_survived_.Push(MakeBytesAndDuration( recorded_minor_gcs_survived_.Push(MakeBytesAndDuration(
current_.survived_new_space_object_size, duration)); current_.survived_new_space_object_size, duration));
FetchBackgroundMinorGCCounters();
break; break;
case Event::INCREMENTAL_MARK_COMPACTOR: case Event::INCREMENTAL_MARK_COMPACTOR:
current_.incremental_marking_bytes = incremental_marking_bytes_; current_.incremental_marking_bytes = incremental_marking_bytes_;
...@@ -280,6 +311,7 @@ void GCTracer::Stop(GarbageCollector collector) { ...@@ -280,6 +311,7 @@ void GCTracer::Stop(GarbageCollector collector) {
MakeBytesAndDuration(current_.start_object_size, duration)); MakeBytesAndDuration(current_.start_object_size, duration));
ResetIncrementalMarkingCounters(); ResetIncrementalMarkingCounters();
combined_mark_compact_speed_cache_ = 0.0; combined_mark_compact_speed_cache_ = 0.0;
FetchBackgroundMarkCompactCounters();
break; break;
case Event::MARK_COMPACTOR: case Event::MARK_COMPACTOR:
DCHECK_EQ(0u, current_.incremental_marking_bytes); DCHECK_EQ(0u, current_.incremental_marking_bytes);
...@@ -288,6 +320,7 @@ void GCTracer::Stop(GarbageCollector collector) { ...@@ -288,6 +320,7 @@ void GCTracer::Stop(GarbageCollector collector) {
MakeBytesAndDuration(current_.start_object_size, duration)); MakeBytesAndDuration(current_.start_object_size, duration));
ResetIncrementalMarkingCounters(); ResetIncrementalMarkingCounters();
combined_mark_compact_speed_cache_ = 0.0; combined_mark_compact_speed_cache_ = 0.0;
FetchBackgroundMarkCompactCounters();
break; break;
case Event::START: case Event::START:
UNREACHABLE(); UNREACHABLE();
...@@ -466,6 +499,7 @@ void GCTracer::PrintNVP() const { ...@@ -466,6 +499,7 @@ void GCTracer::PrintNVP() const {
"scavenge.weak_global_handles.identify=%.2f " "scavenge.weak_global_handles.identify=%.2f "
"scavenge.weak_global_handles.process=%.2f " "scavenge.weak_global_handles.process=%.2f "
"scavenge.parallel=%.2f " "scavenge.parallel=%.2f "
"background.scavenge.parallel=%.2f "
"incremental.steps_count=%d " "incremental.steps_count=%d "
"incremental.steps_took=%.1f " "incremental.steps_took=%.1f "
"scavenge_throughput=%.f " "scavenge_throughput=%.f "
...@@ -511,6 +545,7 @@ void GCTracer::PrintNVP() const { ...@@ -511,6 +545,7 @@ void GCTracer::PrintNVP() const {
current_ current_
.scopes[Scope::SCAVENGER_SCAVENGE_WEAK_GLOBAL_HANDLES_PROCESS], .scopes[Scope::SCAVENGER_SCAVENGE_WEAK_GLOBAL_HANDLES_PROCESS],
current_.scopes[Scope::SCAVENGER_SCAVENGE_PARALLEL], current_.scopes[Scope::SCAVENGER_SCAVENGE_PARALLEL],
current_.scopes[Scope::SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL],
current_.incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL] current_.incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL]
.steps, .steps,
current_.scopes[Scope::MC_INCREMENTAL], current_.scopes[Scope::MC_INCREMENTAL],
...@@ -549,6 +584,9 @@ void GCTracer::PrintNVP() const { ...@@ -549,6 +584,9 @@ void GCTracer::PrintNVP() const {
"evacuate.update_pointers=%.2f " "evacuate.update_pointers=%.2f "
"evacuate.update_pointers.to_new_roots=%.2f " "evacuate.update_pointers.to_new_roots=%.2f "
"evacuate.update_pointers.slots=%.2f " "evacuate.update_pointers.slots=%.2f "
"background.mark=%.2f "
"background.evacuate.copy=%.2f "
"background.evacuate.update_pointers=%.2f "
"update_marking_deque=%.2f " "update_marking_deque=%.2f "
"reset_liveness=%.2f\n", "reset_liveness=%.2f\n",
duration, spent_in_mutator, "mmc", current_.reduce_memory, duration, spent_in_mutator, "mmc", current_.reduce_memory,
...@@ -568,6 +606,9 @@ void GCTracer::PrintNVP() const { ...@@ -568,6 +606,9 @@ void GCTracer::PrintNVP() const {
current_ current_
.scopes[Scope::MINOR_MC_EVACUATE_UPDATE_POINTERS_TO_NEW_ROOTS], .scopes[Scope::MINOR_MC_EVACUATE_UPDATE_POINTERS_TO_NEW_ROOTS],
current_.scopes[Scope::MINOR_MC_EVACUATE_UPDATE_POINTERS_SLOTS], current_.scopes[Scope::MINOR_MC_EVACUATE_UPDATE_POINTERS_SLOTS],
current_.scopes[Scope::MINOR_MC_BACKGROUND_MARKING],
current_.scopes[Scope::MINOR_MC_BACKGROUND_EVACUATE_COPY],
current_.scopes[Scope::MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS],
current_.scopes[Scope::MINOR_MC_MARKING_DEQUE], current_.scopes[Scope::MINOR_MC_MARKING_DEQUE],
current_.scopes[Scope::MINOR_MC_RESET_LIVENESS]); current_.scopes[Scope::MINOR_MC_RESET_LIVENESS]);
break; break;
...@@ -639,6 +680,10 @@ void GCTracer::PrintNVP() const { ...@@ -639,6 +680,10 @@ void GCTracer::PrintNVP() const {
"incremental_steps_count=%d " "incremental_steps_count=%d "
"incremental_marking_throughput=%.f " "incremental_marking_throughput=%.f "
"incremental_walltime_duration=%.f " "incremental_walltime_duration=%.f "
"background.mark=%.1f "
"background.sweep=%.1f "
"background.evacuate.copy=%.1f "
"background.evacuate.update_pointers=%.1f "
"total_size_before=%" PRIuS "total_size_before=%" PRIuS
" " " "
"total_size_after=%" PRIuS "total_size_after=%" PRIuS
...@@ -731,10 +776,14 @@ void GCTracer::PrintNVP() const { ...@@ -731,10 +776,14 @@ void GCTracer::PrintNVP() const {
.longest_step, .longest_step,
current_.incremental_marking_scopes[Scope::MC_INCREMENTAL].steps, current_.incremental_marking_scopes[Scope::MC_INCREMENTAL].steps,
IncrementalMarkingSpeedInBytesPerMillisecond(), IncrementalMarkingSpeedInBytesPerMillisecond(),
incremental_walltime_duration, current_.start_object_size, incremental_walltime_duration,
current_.end_object_size, current_.start_holes_size, current_.scopes[Scope::MC_BACKGROUND_MARKING],
current_.end_holes_size, allocated_since_last_gc, current_.scopes[Scope::MC_BACKGROUND_SWEEPING],
heap_->promoted_objects_size(), current_.scopes[Scope::MC_BACKGROUND_EVACUATE_COPY],
current_.scopes[Scope::MC_BACKGROUND_EVACUATE_UPDATE_POINTERS],
current_.start_object_size, current_.end_object_size,
current_.start_holes_size, current_.end_holes_size,
allocated_since_last_gc, heap_->promoted_objects_size(),
heap_->semi_space_copied_object_size(), heap_->semi_space_copied_object_size(),
heap_->nodes_died_in_new_space_, heap_->nodes_copied_in_new_space_, heap_->nodes_died_in_new_space_, heap_->nodes_copied_in_new_space_,
heap_->nodes_promoted_, heap_->promotion_ratio_, heap_->nodes_promoted_, heap_->promotion_ratio_,
...@@ -898,5 +947,58 @@ void GCTracer::NotifyIncrementalMarkingStart() { ...@@ -898,5 +947,58 @@ void GCTracer::NotifyIncrementalMarkingStart() {
incremental_marking_start_time_ = heap_->MonotonicallyIncreasingTimeInMs(); incremental_marking_start_time_ = heap_->MonotonicallyIncreasingTimeInMs();
} }
void GCTracer::FetchBackgroundMarkCompactCounters() {
FetchBackgroundCounters(Scope::FIRST_MC_BACKGROUND_SCOPE,
Scope::LAST_MC_BACKGROUND_SCOPE,
BackgroundScope::FIRST_MC_BACKGROUND_SCOPE,
BackgroundScope::LAST_MC_BACKGROUND_SCOPE);
}
void GCTracer::FetchBackgroundMinorGCCounters() {
FetchBackgroundCounters(Scope::FIRST_MINOR_GC_BACKGROUND_SCOPE,
Scope::LAST_MINOR_GC_BACKGROUND_SCOPE,
BackgroundScope::FIRST_MINOR_GC_BACKGROUND_SCOPE,
BackgroundScope::LAST_MINOR_GC_BACKGROUND_SCOPE);
}
void GCTracer::FetchBackgroundCounters(int first_global_scope,
int last_global_scope,
int first_background_scope,
int last_background_scope) {
DCHECK_EQ(last_global_scope - first_global_scope,
last_background_scope - first_background_scope);
base::LockGuard<base::Mutex> guard(&background_counter_mutex_);
int background_mc_scopes = last_background_scope - first_background_scope + 1;
for (int i = 0; i < background_mc_scopes; i++) {
current_.scopes[first_global_scope + i] +=
background_counter_[first_background_scope + i].total_duration_ms;
background_counter_[first_background_scope + i].total_duration_ms = 0;
}
if (V8_LIKELY(!FLAG_runtime_stats)) return;
RuntimeCallStats* runtime_stats =
heap_->isolate()->counters()->runtime_call_stats();
if (!runtime_stats) return;
for (int i = 0; i < background_mc_scopes; i++) {
runtime_stats
->GetCounter(GCTracer::RCSCounterFromScope(
static_cast<Scope::ScopeId>(first_global_scope + i)))
->Add(&background_counter_[first_background_scope + i]
.runtime_call_counter);
background_counter_[first_background_scope + i]
.runtime_call_counter.Reset();
}
}
void GCTracer::AddBackgroundScopeSample(
BackgroundScope::ScopeId scope, double duration,
RuntimeCallCounter* runtime_call_counter) {
base::LockGuard<base::Mutex> guard(&background_counter_mutex_);
BackgroundCounter& counter = background_counter_[scope];
counter.total_duration_ms += duration;
if (runtime_call_counter) {
counter.runtime_call_counter.Add(runtime_call_counter);
}
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -61,7 +61,7 @@ class V8_EXPORT_PRIVATE GCTracer { ...@@ -61,7 +61,7 @@ class V8_EXPORT_PRIVATE GCTracer {
public: public:
enum ScopeId { enum ScopeId {
#define DEFINE_SCOPE(scope) scope, #define DEFINE_SCOPE(scope) scope,
TRACER_SCOPES(DEFINE_SCOPE) TRACER_SCOPES(DEFINE_SCOPE) TRACER_BACKGROUND_SCOPES(DEFINE_SCOPE)
#undef DEFINE_SCOPE #undef DEFINE_SCOPE
NUMBER_OF_SCOPES, NUMBER_OF_SCOPES,
...@@ -69,7 +69,12 @@ class V8_EXPORT_PRIVATE GCTracer { ...@@ -69,7 +69,12 @@ class V8_EXPORT_PRIVATE GCTracer {
LAST_INCREMENTAL_SCOPE = MC_INCREMENTAL_EXTERNAL_PROLOGUE, LAST_INCREMENTAL_SCOPE = MC_INCREMENTAL_EXTERNAL_PROLOGUE,
FIRST_SCOPE = MC_INCREMENTAL, FIRST_SCOPE = MC_INCREMENTAL,
NUMBER_OF_INCREMENTAL_SCOPES = NUMBER_OF_INCREMENTAL_SCOPES =
LAST_INCREMENTAL_SCOPE - FIRST_INCREMENTAL_SCOPE + 1 LAST_INCREMENTAL_SCOPE - FIRST_INCREMENTAL_SCOPE + 1,
FIRST_MC_BACKGROUND_SCOPE = MC_BACKGROUND_MARKING,
LAST_MC_BACKGROUND_SCOPE = MC_BACKGROUND_EVACUATE_UPDATE_POINTERS,
FIRST_MINOR_GC_BACKGROUND_SCOPE = SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL,
LAST_MINOR_GC_BACKGROUND_SCOPE =
MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS
}; };
Scope(GCTracer* tracer, ScopeId scope); Scope(GCTracer* tracer, ScopeId scope);
...@@ -86,6 +91,32 @@ class V8_EXPORT_PRIVATE GCTracer { ...@@ -86,6 +91,32 @@ class V8_EXPORT_PRIVATE GCTracer {
DISALLOW_COPY_AND_ASSIGN(Scope); DISALLOW_COPY_AND_ASSIGN(Scope);
}; };
class V8_EXPORT_PRIVATE BackgroundScope {
public:
enum ScopeId {
#define DEFINE_SCOPE(scope) scope,
TRACER_BACKGROUND_SCOPES(DEFINE_SCOPE)
#undef DEFINE_SCOPE
NUMBER_OF_SCOPES,
FIRST_MC_BACKGROUND_SCOPE = MC_BACKGROUND_MARKING,
LAST_MC_BACKGROUND_SCOPE = MC_BACKGROUND_EVACUATE_UPDATE_POINTERS,
FIRST_MINOR_GC_BACKGROUND_SCOPE = SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL,
LAST_MINOR_GC_BACKGROUND_SCOPE =
MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS
};
BackgroundScope(GCTracer* tracer, ScopeId scope);
~BackgroundScope();
private:
GCTracer* tracer_;
ScopeId scope_;
double start_time_;
RuntimeCallTimer timer_;
RuntimeCallCounter counter_;
bool runtime_stats_enabled_;
DISALLOW_COPY_AND_ASSIGN(BackgroundScope);
};
class Event { class Event {
public: public:
...@@ -272,9 +303,16 @@ class V8_EXPORT_PRIVATE GCTracer { ...@@ -272,9 +303,16 @@ class V8_EXPORT_PRIVATE GCTracer {
} }
} }
void AddBackgroundScopeSample(BackgroundScope::ScopeId scope, double duration,
RuntimeCallCounter* runtime_call_counter);
private: private:
FRIEND_TEST(GCTracer, AverageSpeed); FRIEND_TEST(GCTracer, AverageSpeed);
FRIEND_TEST(GCTracerTest, AllocationThroughput); FRIEND_TEST(GCTracerTest, AllocationThroughput);
FRIEND_TEST(GCTracerTest, BackgroundScavengerScope);
FRIEND_TEST(GCTracerTest, BackgroundMinorMCScope);
FRIEND_TEST(GCTracerTest, BackgroundMajorMCScope);
FRIEND_TEST(GCTracerTest, MultithreadedBackgroundScope);
FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughput); FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughput);
FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughputWithProvidedTime); FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughputWithProvidedTime);
FRIEND_TEST(GCTracerTest, OldGenerationAllocationThroughputWithProvidedTime); FRIEND_TEST(GCTracerTest, OldGenerationAllocationThroughputWithProvidedTime);
...@@ -283,6 +321,11 @@ class V8_EXPORT_PRIVATE GCTracer { ...@@ -283,6 +321,11 @@ class V8_EXPORT_PRIVATE GCTracer {
FRIEND_TEST(GCTracerTest, IncrementalScope); FRIEND_TEST(GCTracerTest, IncrementalScope);
FRIEND_TEST(GCTracerTest, IncrementalMarkingSpeed); FRIEND_TEST(GCTracerTest, IncrementalMarkingSpeed);
struct BackgroundCounter {
double total_duration_ms;
RuntimeCallCounter runtime_call_counter;
};
// Returns the average speed of the events in the buffer. // Returns the average speed of the events in the buffer.
// If the buffer is empty, the result is 0. // If the buffer is empty, the result is 0.
// Otherwise, the result is between 1 byte/ms and 1 GB/ms. // Otherwise, the result is between 1 byte/ms and 1 GB/ms.
...@@ -314,6 +357,12 @@ class V8_EXPORT_PRIVATE GCTracer { ...@@ -314,6 +357,12 @@ class V8_EXPORT_PRIVATE GCTracer {
current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE]; current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE];
} }
void FetchBackgroundCounters(int first_global_scope, int last_global_scope,
int first_background_scope,
int last_background_scope);
void FetchBackgroundMinorGCCounters();
void FetchBackgroundMarkCompactCounters();
// Pointer to the heap that owns this tracer. // Pointer to the heap that owns this tracer.
Heap* heap_; Heap* heap_;
...@@ -367,8 +416,12 @@ class V8_EXPORT_PRIVATE GCTracer { ...@@ -367,8 +416,12 @@ class V8_EXPORT_PRIVATE GCTracer {
base::RingBuffer<double> recorded_context_disposal_times_; base::RingBuffer<double> recorded_context_disposal_times_;
base::RingBuffer<double> recorded_survival_ratios_; base::RingBuffer<double> recorded_survival_ratios_;
base::Mutex background_counter_mutex_;
BackgroundCounter background_counter_[BackgroundScope::NUMBER_OF_SCOPES];
DISALLOW_COPY_AND_ASSIGN(GCTracer); DISALLOW_COPY_AND_ASSIGN(GCTracer);
}; };
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -1908,6 +1908,7 @@ class ScavengingTask final : public ItemParallelJob::Task { ...@@ -1908,6 +1908,7 @@ class ScavengingTask final : public ItemParallelJob::Task {
barrier_(barrier) {} barrier_(barrier) {}
void RunInParallel() final { void RunInParallel() final {
// TODO(ulan): add GCTracer background scope.
double scavenging_time = 0.0; double scavenging_time = 0.0;
{ {
barrier_->Start(); barrier_->Start();
......
...@@ -1868,6 +1868,7 @@ class YoungGenerationMarkingTask : public ItemParallelJob::Task { ...@@ -1868,6 +1868,7 @@ class YoungGenerationMarkingTask : public ItemParallelJob::Task {
} }
void RunInParallel() override { void RunInParallel() override {
// TODO(ulan): add GCTracer background scope.
double marking_time = 0.0; double marking_time = 0.0;
{ {
TimedScope scope(&marking_time); TimedScope scope(&marking_time);
...@@ -3246,6 +3247,7 @@ class PageEvacuationTask : public ItemParallelJob::Task { ...@@ -3246,6 +3247,7 @@ class PageEvacuationTask : public ItemParallelJob::Task {
: ItemParallelJob::Task(isolate), evacuator_(evacuator) {} : ItemParallelJob::Task(isolate), evacuator_(evacuator) {}
void RunInParallel() override { void RunInParallel() override {
// TODO(ulan): add GCTracer background scope.
PageEvacuationItem* item = nullptr; PageEvacuationItem* item = nullptr;
while ((item = GetItem<PageEvacuationItem>()) != nullptr) { while ((item = GetItem<PageEvacuationItem>()) != nullptr) {
evacuator_->EvacuatePage(item->page()); evacuator_->EvacuatePage(item->page());
...@@ -3557,6 +3559,7 @@ class PointersUpdatingTask : public ItemParallelJob::Task { ...@@ -3557,6 +3559,7 @@ class PointersUpdatingTask : public ItemParallelJob::Task {
: ItemParallelJob::Task(isolate) {} : ItemParallelJob::Task(isolate) {}
void RunInParallel() override { void RunInParallel() override {
// TODO(ulan): add GCTracer background scope.
UpdatingItem* item = nullptr; UpdatingItem* item = nullptr;
while ((item = GetItem<UpdatingItem>()) != nullptr) { while ((item = GetItem<UpdatingItem>()) != nullptr) {
item->Process(); item->Process();
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "src/heap/sweeper.h" #include "src/heap/sweeper.h"
#include "src/heap/array-buffer-tracker-inl.h" #include "src/heap/array-buffer-tracker-inl.h"
#include "src/heap/gc-tracer.h"
#include "src/heap/mark-compact-inl.h" #include "src/heap/mark-compact-inl.h"
#include "src/heap/remembered-set.h" #include "src/heap/remembered-set.h"
#include "src/objects-inl.h" #include "src/objects-inl.h"
...@@ -68,12 +69,14 @@ class Sweeper::SweeperTask final : public CancelableTask { ...@@ -68,12 +69,14 @@ class Sweeper::SweeperTask final : public CancelableTask {
sweeper_(sweeper), sweeper_(sweeper),
pending_sweeper_tasks_(pending_sweeper_tasks), pending_sweeper_tasks_(pending_sweeper_tasks),
num_sweeping_tasks_(num_sweeping_tasks), num_sweeping_tasks_(num_sweeping_tasks),
space_to_start_(space_to_start) {} space_to_start_(space_to_start),
tracer_(isolate->heap()->tracer()) {}
virtual ~SweeperTask() {} virtual ~SweeperTask() {}
private: private:
void RunInternal() final { void RunInternal() final {
// TODO(ulan): add GCTracer background scope.
DCHECK_GE(space_to_start_, FIRST_PAGED_SPACE); DCHECK_GE(space_to_start_, FIRST_PAGED_SPACE);
DCHECK_LE(space_to_start_, LAST_PAGED_SPACE); DCHECK_LE(space_to_start_, LAST_PAGED_SPACE);
const int offset = space_to_start_ - FIRST_PAGED_SPACE; const int offset = space_to_start_ - FIRST_PAGED_SPACE;
...@@ -94,6 +97,7 @@ class Sweeper::SweeperTask final : public CancelableTask { ...@@ -94,6 +97,7 @@ class Sweeper::SweeperTask final : public CancelableTask {
base::Semaphore* const pending_sweeper_tasks_; base::Semaphore* const pending_sweeper_tasks_;
base::AtomicNumber<intptr_t>* const num_sweeping_tasks_; base::AtomicNumber<intptr_t>* const num_sweeping_tasks_;
AllocationSpace space_to_start_; AllocationSpace space_to_start_;
GCTracer* const tracer_;
DISALLOW_COPY_AND_ASSIGN(SweeperTask); DISALLOW_COPY_AND_ASSIGN(SweeperTask);
}; };
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <cmath> #include <cmath>
#include <limits> #include <limits>
#include "src/base/platform/platform.h"
#include "src/globals.h" #include "src/globals.h"
#include "src/heap/gc-tracer.h" #include "src/heap/gc-tracer.h"
#include "src/isolate.h" #include "src/isolate.h"
...@@ -294,5 +295,125 @@ TEST_F(GCTracerTest, IncrementalMarkingSpeed) { ...@@ -294,5 +295,125 @@ TEST_F(GCTracerTest, IncrementalMarkingSpeed) {
tracer->IncrementalMarkingSpeedInBytesPerMillisecond())); tracer->IncrementalMarkingSpeedInBytesPerMillisecond()));
} }
TEST_F(GCTracerTest, BackgroundScavengerScope) {
GCTracer* tracer = i_isolate()->heap()->tracer();
tracer->ResetForTesting();
tracer->Start(SCAVENGER, GarbageCollectionReason::kTesting,
"collector unittest");
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL, 10,
nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL, 1,
nullptr);
tracer->Stop(SCAVENGER);
EXPECT_DOUBLE_EQ(
11, tracer->current_
.scopes[GCTracer::Scope::SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL]);
}
TEST_F(GCTracerTest, BackgroundMinorMCScope) {
GCTracer* tracer = i_isolate()->heap()->tracer();
tracer->ResetForTesting();
tracer->Start(MINOR_MARK_COMPACTOR, GarbageCollectionReason::kTesting,
"collector unittest");
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_MARKING, 10, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_MARKING, 1, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_EVACUATE_COPY, 20,
nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_EVACUATE_COPY, 2, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS,
30, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS,
3, nullptr);
tracer->Stop(MINOR_MARK_COMPACTOR);
EXPECT_DOUBLE_EQ(
11,
tracer->current_.scopes[GCTracer::Scope::MINOR_MC_BACKGROUND_MARKING]);
EXPECT_DOUBLE_EQ(
22, tracer->current_
.scopes[GCTracer::Scope::MINOR_MC_BACKGROUND_EVACUATE_COPY]);
EXPECT_DOUBLE_EQ(
33, tracer->current_.scopes
[GCTracer::Scope::MINOR_MC_BACKGROUND_EVACUATE_UPDATE_POINTERS]);
}
TEST_F(GCTracerTest, BackgroundMajorMCScope) {
GCTracer* tracer = i_isolate()->heap()->tracer();
tracer->ResetForTesting();
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_MARKING, 100, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_SWEEPING, 200, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_MARKING, 10, nullptr);
// Scavenger should not affect the major mark-compact scopes.
tracer->Start(SCAVENGER, GarbageCollectionReason::kTesting,
"collector unittest");
tracer->Stop(SCAVENGER);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_SWEEPING, 20, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_MARKING, 1, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_SWEEPING, 2, nullptr);
tracer->Start(MARK_COMPACTOR, GarbageCollectionReason::kTesting,
"collector unittest");
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_EVACUATE_COPY, 30, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_EVACUATE_COPY, 3, nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_EVACUATE_UPDATE_POINTERS, 40,
nullptr);
tracer->AddBackgroundScopeSample(
GCTracer::BackgroundScope::MC_BACKGROUND_EVACUATE_UPDATE_POINTERS, 4,
nullptr);
tracer->Stop(MARK_COMPACTOR);
EXPECT_DOUBLE_EQ(
111, tracer->current_.scopes[GCTracer::Scope::MC_BACKGROUND_MARKING]);
EXPECT_DOUBLE_EQ(
222, tracer->current_.scopes[GCTracer::Scope::MC_BACKGROUND_SWEEPING]);
EXPECT_DOUBLE_EQ(
33,
tracer->current_.scopes[GCTracer::Scope::MC_BACKGROUND_EVACUATE_COPY]);
EXPECT_DOUBLE_EQ(
44, tracer->current_
.scopes[GCTracer::Scope::MC_BACKGROUND_EVACUATE_UPDATE_POINTERS]);
}
class ThreadWithBackgroundScope final : public base::Thread {
public:
explicit ThreadWithBackgroundScope(GCTracer* tracer)
: Thread(Options("ThreadWithBackgroundScope")), tracer_(tracer) {}
void Run() override {
GCTracer::BackgroundScope scope(
tracer_, GCTracer::BackgroundScope::MC_BACKGROUND_MARKING);
}
private:
GCTracer* tracer_;
};
TEST_F(GCTracerTest, MultithreadedBackgroundScope) {
GCTracer* tracer = i_isolate()->heap()->tracer();
ThreadWithBackgroundScope thread1(tracer);
ThreadWithBackgroundScope thread2(tracer);
tracer->ResetForTesting();
thread1.Start();
thread2.Start();
tracer->FetchBackgroundMarkCompactCounters();
thread1.Join();
thread2.Join();
tracer->FetchBackgroundMarkCompactCounters();
EXPECT_LE(0, tracer->current_.scopes[GCTracer::Scope::MC_BACKGROUND_MARKING]);
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
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