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,
class RuntimeCallCounter final {
public:
RuntimeCallCounter() : RuntimeCallCounter(nullptr) {}
explicit RuntimeCallCounter(const char* name)
: name_(name), count_(0), time_(0) {}
V8_NOINLINE void Reset();
......@@ -596,8 +597,6 @@ class RuntimeCallCounter final {
private:
friend class RuntimeCallStats;
RuntimeCallCounter() {}
const char* name_;
int64_t count_;
// Stored as int64_t so that its initialization can be deferred.
......@@ -634,7 +633,9 @@ class RuntimeCallTimer final {
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) \
V(ArrayBuffer_Cast) \
......
......@@ -356,4 +356,14 @@
F(SCAVENGER_SCAVENGE_ROOTS) \
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_
......@@ -7,6 +7,7 @@
#include <stack>
#include <unordered_map>
#include "src/heap/gc-tracer.h"
#include "src/heap/heap-inl.h"
#include "src/heap/heap.h"
#include "src/heap/mark-compact-inl.h"
......@@ -427,6 +428,7 @@ ConcurrentMarking::ConcurrentMarking(Heap* heap, MarkingWorklist* shared,
}
void ConcurrentMarking::Run(int task_id, TaskState* task_state) {
// TODO(ulan): add GCTracer background scope.
size_t kBytesUntilInterruptCheck = 64 * KB;
int kObjectsUntilInterrupCheck = 1000;
LiveBytesMap* live_bytes = nullptr;
......
......@@ -48,12 +48,34 @@ GCTracer::Scope::~Scope() {
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) {
#define CASE(scope) \
case Scope::scope: \
return "V8.GC_" #scope;
switch (id) {
TRACER_SCOPES(CASE)
TRACER_BACKGROUND_SCOPES(CASE)
case Scope::NUMBER_OF_SCOPES:
break;
}
......@@ -122,6 +144,10 @@ GCTracer::GCTracer(Heap* heap)
// map it to RuntimeCallStats.
STATIC_ASSERT(0 == Scope::MC_INCREMENTAL);
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() {
......@@ -146,6 +172,10 @@ void GCTracer::ResetForTesting() {
recorded_context_disposal_times_.Reset();
recorded_survival_ratios_.Reset();
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(
......@@ -266,6 +296,7 @@ void GCTracer::Stop(GarbageCollector collector) {
MakeBytesAndDuration(current_.new_space_object_size, duration));
recorded_minor_gcs_survived_.Push(MakeBytesAndDuration(
current_.survived_new_space_object_size, duration));
FetchBackgroundMinorGCCounters();
break;
case Event::INCREMENTAL_MARK_COMPACTOR:
current_.incremental_marking_bytes = incremental_marking_bytes_;
......@@ -280,6 +311,7 @@ void GCTracer::Stop(GarbageCollector collector) {
MakeBytesAndDuration(current_.start_object_size, duration));
ResetIncrementalMarkingCounters();
combined_mark_compact_speed_cache_ = 0.0;
FetchBackgroundMarkCompactCounters();
break;
case Event::MARK_COMPACTOR:
DCHECK_EQ(0u, current_.incremental_marking_bytes);
......@@ -288,6 +320,7 @@ void GCTracer::Stop(GarbageCollector collector) {
MakeBytesAndDuration(current_.start_object_size, duration));
ResetIncrementalMarkingCounters();
combined_mark_compact_speed_cache_ = 0.0;
FetchBackgroundMarkCompactCounters();
break;
case Event::START:
UNREACHABLE();
......@@ -466,6 +499,7 @@ void GCTracer::PrintNVP() const {
"scavenge.weak_global_handles.identify=%.2f "
"scavenge.weak_global_handles.process=%.2f "
"scavenge.parallel=%.2f "
"background.scavenge.parallel=%.2f "
"incremental.steps_count=%d "
"incremental.steps_took=%.1f "
"scavenge_throughput=%.f "
......@@ -511,6 +545,7 @@ void GCTracer::PrintNVP() const {
current_
.scopes[Scope::SCAVENGER_SCAVENGE_WEAK_GLOBAL_HANDLES_PROCESS],
current_.scopes[Scope::SCAVENGER_SCAVENGE_PARALLEL],
current_.scopes[Scope::SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL],
current_.incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL]
.steps,
current_.scopes[Scope::MC_INCREMENTAL],
......@@ -549,6 +584,9 @@ void GCTracer::PrintNVP() const {
"evacuate.update_pointers=%.2f "
"evacuate.update_pointers.to_new_roots=%.2f "
"evacuate.update_pointers.slots=%.2f "
"background.mark=%.2f "
"background.evacuate.copy=%.2f "
"background.evacuate.update_pointers=%.2f "
"update_marking_deque=%.2f "
"reset_liveness=%.2f\n",
duration, spent_in_mutator, "mmc", current_.reduce_memory,
......@@ -568,6 +606,9 @@ void GCTracer::PrintNVP() const {
current_
.scopes[Scope::MINOR_MC_EVACUATE_UPDATE_POINTERS_TO_NEW_ROOTS],
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_RESET_LIVENESS]);
break;
......@@ -639,6 +680,10 @@ void GCTracer::PrintNVP() const {
"incremental_steps_count=%d "
"incremental_marking_throughput=%.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_after=%" PRIuS
......@@ -731,10 +776,14 @@ void GCTracer::PrintNVP() const {
.longest_step,
current_.incremental_marking_scopes[Scope::MC_INCREMENTAL].steps,
IncrementalMarkingSpeedInBytesPerMillisecond(),
incremental_walltime_duration, current_.start_object_size,
current_.end_object_size, current_.start_holes_size,
current_.end_holes_size, allocated_since_last_gc,
heap_->promoted_objects_size(),
incremental_walltime_duration,
current_.scopes[Scope::MC_BACKGROUND_MARKING],
current_.scopes[Scope::MC_BACKGROUND_SWEEPING],
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_->nodes_died_in_new_space_, heap_->nodes_copied_in_new_space_,
heap_->nodes_promoted_, heap_->promotion_ratio_,
......@@ -898,5 +947,58 @@ void GCTracer::NotifyIncrementalMarkingStart() {
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 v8
......@@ -61,7 +61,7 @@ class V8_EXPORT_PRIVATE GCTracer {
public:
enum ScopeId {
#define DEFINE_SCOPE(scope) scope,
TRACER_SCOPES(DEFINE_SCOPE)
TRACER_SCOPES(DEFINE_SCOPE) TRACER_BACKGROUND_SCOPES(DEFINE_SCOPE)
#undef DEFINE_SCOPE
NUMBER_OF_SCOPES,
......@@ -69,7 +69,12 @@ class V8_EXPORT_PRIVATE GCTracer {
LAST_INCREMENTAL_SCOPE = MC_INCREMENTAL_EXTERNAL_PROLOGUE,
FIRST_SCOPE = MC_INCREMENTAL,
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);
......@@ -86,6 +91,32 @@ class V8_EXPORT_PRIVATE GCTracer {
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 {
public:
......@@ -272,9 +303,16 @@ class V8_EXPORT_PRIVATE GCTracer {
}
}
void AddBackgroundScopeSample(BackgroundScope::ScopeId scope, double duration,
RuntimeCallCounter* runtime_call_counter);
private:
FRIEND_TEST(GCTracer, AverageSpeed);
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, NewSpaceAllocationThroughputWithProvidedTime);
FRIEND_TEST(GCTracerTest, OldGenerationAllocationThroughputWithProvidedTime);
......@@ -283,6 +321,11 @@ class V8_EXPORT_PRIVATE GCTracer {
FRIEND_TEST(GCTracerTest, IncrementalScope);
FRIEND_TEST(GCTracerTest, IncrementalMarkingSpeed);
struct BackgroundCounter {
double total_duration_ms;
RuntimeCallCounter runtime_call_counter;
};
// Returns the average speed of the events in the buffer.
// If the buffer is empty, the result is 0.
// Otherwise, the result is between 1 byte/ms and 1 GB/ms.
......@@ -314,6 +357,12 @@ class V8_EXPORT_PRIVATE GCTracer {
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.
Heap* heap_;
......@@ -367,8 +416,12 @@ class V8_EXPORT_PRIVATE GCTracer {
base::RingBuffer<double> recorded_context_disposal_times_;
base::RingBuffer<double> recorded_survival_ratios_;
base::Mutex background_counter_mutex_;
BackgroundCounter background_counter_[BackgroundScope::NUMBER_OF_SCOPES];
DISALLOW_COPY_AND_ASSIGN(GCTracer);
};
} // namespace internal
} // namespace v8
......
......@@ -1908,6 +1908,7 @@ class ScavengingTask final : public ItemParallelJob::Task {
barrier_(barrier) {}
void RunInParallel() final {
// TODO(ulan): add GCTracer background scope.
double scavenging_time = 0.0;
{
barrier_->Start();
......
......@@ -1868,6 +1868,7 @@ class YoungGenerationMarkingTask : public ItemParallelJob::Task {
}
void RunInParallel() override {
// TODO(ulan): add GCTracer background scope.
double marking_time = 0.0;
{
TimedScope scope(&marking_time);
......@@ -3246,6 +3247,7 @@ class PageEvacuationTask : public ItemParallelJob::Task {
: ItemParallelJob::Task(isolate), evacuator_(evacuator) {}
void RunInParallel() override {
// TODO(ulan): add GCTracer background scope.
PageEvacuationItem* item = nullptr;
while ((item = GetItem<PageEvacuationItem>()) != nullptr) {
evacuator_->EvacuatePage(item->page());
......@@ -3557,6 +3559,7 @@ class PointersUpdatingTask : public ItemParallelJob::Task {
: ItemParallelJob::Task(isolate) {}
void RunInParallel() override {
// TODO(ulan): add GCTracer background scope.
UpdatingItem* item = nullptr;
while ((item = GetItem<UpdatingItem>()) != nullptr) {
item->Process();
......
......@@ -5,6 +5,7 @@
#include "src/heap/sweeper.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/remembered-set.h"
#include "src/objects-inl.h"
......@@ -68,12 +69,14 @@ class Sweeper::SweeperTask final : public CancelableTask {
sweeper_(sweeper),
pending_sweeper_tasks_(pending_sweeper_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() {}
private:
void RunInternal() final {
// TODO(ulan): add GCTracer background scope.
DCHECK_GE(space_to_start_, FIRST_PAGED_SPACE);
DCHECK_LE(space_to_start_, LAST_PAGED_SPACE);
const int offset = space_to_start_ - FIRST_PAGED_SPACE;
......@@ -94,6 +97,7 @@ class Sweeper::SweeperTask final : public CancelableTask {
base::Semaphore* const pending_sweeper_tasks_;
base::AtomicNumber<intptr_t>* const num_sweeping_tasks_;
AllocationSpace space_to_start_;
GCTracer* const tracer_;
DISALLOW_COPY_AND_ASSIGN(SweeperTask);
};
......
......@@ -5,6 +5,7 @@
#include <cmath>
#include <limits>
#include "src/base/platform/platform.h"
#include "src/globals.h"
#include "src/heap/gc-tracer.h"
#include "src/isolate.h"
......@@ -294,5 +295,125 @@ TEST_F(GCTracerTest, IncrementalMarkingSpeed) {
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 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