Commit 300a8f97 authored by mlippautz's avatar mlippautz Committed by Commit bot

[heap] Tracer: Handle incremental marking scopes

Before this patch all tracing scopes in incremental marking would be reset
during a gc tracer start/stop cycle. This patch handles scopes the same way it
does other incremental marking metrics.

Also:
- Align finalization metric with regular marking metric.
- Smaller cleanups

BUG=chromium:639818
R=jochen@chromium.org

Review-Url: https://codereview.chromium.org/2264033002
Cr-Commit-Position: refs/heads/master@{#38822}
parent 30da343d
......@@ -31,17 +31,25 @@ GCTracer::Scope::Scope(GCTracer* tracer, ScopeId scope)
}
}
GCTracer::Scope::~Scope() {
DCHECK(scope_ < NUMBER_OF_SCOPES); // scope_ is unsigned.
tracer_->current_.scopes[scope_] +=
tracer_->heap_->MonotonicallyIncreasingTimeInMs() - start_time_;
tracer_->AddScopeSample(
scope_, tracer_->heap_->MonotonicallyIncreasingTimeInMs() - start_time_);
// TODO(cbruni): remove once we fully moved to a trace-based system.
if (FLAG_runtime_call_stats) {
RuntimeCallStats::Leave(tracer_->heap_->isolate(), &timer_);
}
}
void GCTracer::AddScopeSample(Scope::ScopeId scope, double duration) {
DCHECK(scope < Scope::NUMBER_OF_SCOPES);
if (scope >= Scope::FIRST_INCREMENTAL_SCOPE &&
scope <= Scope::LAST_INCREMENTAL_SCOPE) {
cumulative_incremental_scopes_[scope] += duration;
} else {
current_.scopes[scope] += duration;
}
}
const char* GCTracer::Scope::Name(ScopeId id) {
#define CASE(scope) \
case Scope::scope: \
......@@ -69,6 +77,8 @@ GCTracer::Event::Event(Type type, const char* gc_reason,
end_memory_size(0),
start_holes_size(0),
end_holes_size(0),
new_space_object_size(0),
survived_new_space_object_size(0),
cumulative_incremental_marking_steps(0),
incremental_marking_steps(0),
cumulative_incremental_marking_bytes(0),
......@@ -77,7 +87,15 @@ GCTracer::Event::Event(Type type, const char* gc_reason,
incremental_marking_duration(0.0),
cumulative_pure_incremental_marking_duration(0.0),
pure_incremental_marking_duration(0.0),
longest_incremental_marking_step(0.0) {
longest_incremental_marking_step(0.0),
cumulative_incremental_marking_finalization_steps(0),
cumulative_incremental_marking_finalizaton_duration(0),
longest_incremental_marking_finalization_step(0),
incremental_marking_finalizaton_steps(0),
incremental_marking_finalization_duration(0) {
for (int i = 0; i < Scope::NUMBER_OF_INCREMENTAL_SCOPES; i++) {
cumulative_incremental_scopes[i] = 0;
}
for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) {
scopes[i] = 0;
}
......@@ -196,10 +214,17 @@ void GCTracer::Start(GarbageCollector collector, const char* gc_reason,
current_.cumulative_pure_incremental_marking_duration =
cumulative_pure_incremental_marking_duration_;
current_.longest_incremental_marking_step = longest_incremental_marking_step_;
current_.cumulative_incremental_marking_finalization_steps =
cumulative_incremental_marking_finalization_steps_;
current_.cumulative_incremental_marking_finalizaton_duration =
cumulative_incremental_marking_finalization_duration_;
current_.longest_incremental_marking_finalization_step =
longest_incremental_marking_finalization_step_;
for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) {
current_.scopes[i] = 0;
}
int committed_memory = static_cast<int>(heap_->CommittedMemory() / KB);
int used_memory = static_cast<int>(current_.start_object_size / KB);
heap_->isolate()->counters()->aggregated_memory_heap_committed()->AddSample(
......@@ -227,6 +252,12 @@ void GCTracer::Stop(GarbageCollector collector) {
(current_.type == Event::MARK_COMPACTOR ||
current_.type == Event::INCREMENTAL_MARK_COMPACTOR)));
for (int i = Scope::FIRST_INCREMENTAL_SCOPE;
i <= Scope::LAST_INCREMENTAL_SCOPE; i++) {
current_.cumulative_incremental_scopes[i] =
cumulative_incremental_scopes_[i];
}
current_.end_time = heap_->MonotonicallyIncreasingTimeInMs();
current_.end_object_size = heap_->SizeOfObjects();
current_.end_memory_size = heap_->memory_allocator()->Size();
......@@ -243,41 +274,18 @@ void GCTracer::Stop(GarbageCollector collector) {
current_.end_time, used_memory);
double duration = current_.end_time - current_.start_time;
const Event* baseline = nullptr;
if (current_.type == Event::SCAVENGER) {
current_.incremental_marking_steps =
current_.cumulative_incremental_marking_steps -
previous_.cumulative_incremental_marking_steps;
current_.incremental_marking_bytes =
current_.cumulative_incremental_marking_bytes -
previous_.cumulative_incremental_marking_bytes;
current_.incremental_marking_duration =
current_.cumulative_incremental_marking_duration -
previous_.cumulative_incremental_marking_duration;
current_.pure_incremental_marking_duration =
current_.cumulative_pure_incremental_marking_duration -
previous_.cumulative_pure_incremental_marking_duration;
baseline = &previous_;
recorded_scavenges_total_.Push(
MakeBytesAndDuration(current_.new_space_object_size, duration));
recorded_scavenges_survived_.Push(MakeBytesAndDuration(
current_.survived_new_space_object_size, duration));
} else if (current_.type == Event::INCREMENTAL_MARK_COMPACTOR) {
current_.incremental_marking_steps =
current_.cumulative_incremental_marking_steps -
previous_incremental_mark_compactor_event_
.cumulative_incremental_marking_steps;
current_.incremental_marking_bytes =
current_.cumulative_incremental_marking_bytes -
previous_incremental_mark_compactor_event_
.cumulative_incremental_marking_bytes;
current_.incremental_marking_duration =
current_.cumulative_incremental_marking_duration -
previous_incremental_mark_compactor_event_
.cumulative_incremental_marking_duration;
current_.pure_incremental_marking_duration =
current_.cumulative_pure_incremental_marking_duration -
previous_incremental_mark_compactor_event_
.cumulative_pure_incremental_marking_duration;
baseline = &previous_incremental_mark_compactor_event_;
longest_incremental_marking_step_ = 0.0;
longest_incremental_marking_finalization_step_ = 0.0;
recorded_incremental_marking_steps_.Push(
MakeBytesAndDuration(current_.incremental_marking_bytes,
current_.pure_incremental_marking_duration));
......@@ -289,33 +297,55 @@ void GCTracer::Stop(GarbageCollector collector) {
DCHECK(current_.incremental_marking_duration == 0);
DCHECK(current_.pure_incremental_marking_duration == 0);
longest_incremental_marking_step_ = 0.0;
longest_incremental_marking_finalization_step_ = 0.0;
recorded_mark_compacts_.Push(
MakeBytesAndDuration(current_.start_object_size, duration));
combined_mark_compact_speed_cache_ = 0.0;
}
// TODO(ernstm): move the code below out of GCTracer.
if (baseline != nullptr) {
current_.incremental_marking_steps =
current_.cumulative_incremental_marking_steps -
baseline->cumulative_incremental_marking_steps;
current_.incremental_marking_bytes =
current_.cumulative_incremental_marking_bytes -
baseline->cumulative_incremental_marking_bytes;
current_.incremental_marking_duration =
current_.cumulative_incremental_marking_duration -
baseline->cumulative_incremental_marking_duration;
current_.pure_incremental_marking_duration =
current_.cumulative_pure_incremental_marking_duration -
baseline->cumulative_pure_incremental_marking_duration;
current_.incremental_marking_finalizaton_steps =
current_.cumulative_incremental_marking_finalization_steps -
baseline->cumulative_incremental_marking_finalization_steps;
current_.incremental_marking_finalization_duration =
current_.cumulative_incremental_marking_finalizaton_duration -
baseline->cumulative_incremental_marking_finalizaton_duration;
for (int i = Scope::FIRST_INCREMENTAL_SCOPE;
i <= Scope::LAST_INCREMENTAL_SCOPE; i++) {
current_.scopes[i] = current_.cumulative_incremental_scopes[i] -
baseline->cumulative_incremental_scopes[i];
}
}
double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0);
heap_->UpdateCumulativeGCStatistics(duration, spent_in_mutator,
current_.scopes[Scope::MC_MARK]);
if (current_.type == Event::SCAVENGER && FLAG_trace_gc_ignore_scavenger)
return;
if (FLAG_trace_gc_nvp)
if (FLAG_trace_gc_nvp) {
PrintNVP();
else
} else {
Print();
}
if (FLAG_trace_gc) {
heap_->PrintShortHeapStatistics();
}
longest_incremental_marking_finalization_step_ = 0.0;
cumulative_incremental_marking_finalization_steps_ = 0;
cumulative_incremental_marking_finalization_duration_ = 0.0;
// TODO(cbruni): remove once we fully moved to a trace-based system.
if (FLAG_runtime_call_stats) {
RuntimeCallStats::Leave(heap_->isolate(), &timer_);
......@@ -575,12 +605,11 @@ void GCTracer::PrintNVP() const {
"evacuate.update_pointers.weak=%.1f "
"external.mc_prologue=%.1f "
"external.mc_epilogue=%.1f "
"external.mc_incremental_prologue=%.1f "
"external.mc_incremental_epilogue=%.1f "
"external.weak_global_handles=%.1f "
"finish=%.1f "
"mark=%.1f "
"mark.finish_incremental=%.1f "
"mark.object_grouping=%.1f "
"mark.prepare_code_flush=%.1f "
"mark.roots=%.1f "
"mark.weak_closure=%.1f "
......@@ -588,17 +617,24 @@ void GCTracer::PrintNVP() const {
"mark.weak_closure.weak_handles=%.1f "
"mark.weak_closure.weak_roots=%.1f "
"mark.weak_closure.harmony=%.1f "
"mark.wrapper_prologue=%.1f "
"mark.wrapper_epilogue=%.1f "
"mark.wrapper_tracing=%.1f "
"sweep=%.1f "
"sweep.code=%.1f "
"sweep.map=%.1f "
"sweep.old=%.1f "
"incremental_finalize=%.1f "
"steps_count=%d "
"steps_took=%.1f "
"longest_step=%.1f "
"finalization_steps_count=%d "
"finalization_steps_took=%.1f "
"finalization_longest_step=%.1f "
"incremental=%.1f "
"incremental.finalize=%.1f "
"incremental.finalize.external.prologue=%.1f "
"incremental.finalize.external.epilogue=%.1f "
"incremental.finalize.object_grouping=%.1f "
"incremental.wrapper_prologue=%.1f "
"incremental.wrapper_tracing=%.1f "
"incremental_finalize_longest_step=%.1f "
"incremental_finalize_steps_count=%d "
"incremental_steps_count=%d "
"incremental_longest_step=%.1f "
"incremental_marking_throughput=%.f "
"total_size_before=%" V8PRIdPTR
" "
......@@ -647,11 +683,10 @@ void GCTracer::PrintNVP() const {
current_.scopes[Scope::MC_EVACUATE_UPDATE_POINTERS_WEAK],
current_.scopes[Scope::MC_EXTERNAL_PROLOGUE],
current_.scopes[Scope::MC_EXTERNAL_EPILOGUE],
current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE],
current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_EPILOGUE],
current_.scopes[Scope::EXTERNAL_WEAK_GLOBAL_HANDLES],
current_.scopes[Scope::MC_FINISH], current_.scopes[Scope::MC_MARK],
current_.scopes[Scope::MC_MARK_FINISH_INCREMENTAL],
current_.scopes[Scope::MC_MARK_OBJECT_GROUPING],
current_.scopes[Scope::MC_MARK_PREPARE_CODE_FLUSH],
current_.scopes[Scope::MC_MARK_ROOTS],
current_.scopes[Scope::MC_MARK_WEAK_CLOSURE],
......@@ -659,17 +694,24 @@ void GCTracer::PrintNVP() const {
current_.scopes[Scope::MC_MARK_WEAK_CLOSURE_WEAK_HANDLES],
current_.scopes[Scope::MC_MARK_WEAK_CLOSURE_WEAK_ROOTS],
current_.scopes[Scope::MC_MARK_WEAK_CLOSURE_HARMONY],
current_.scopes[Scope::MC_MARK_WRAPPER_PROLOGUE],
current_.scopes[Scope::MC_MARK_WRAPPER_EPILOGUE],
current_.scopes[Scope::MC_MARK_WRAPPER_TRACING],
current_.scopes[Scope::MC_SWEEP],
current_.scopes[Scope::MC_SWEEP_CODE],
current_.scopes[Scope::MC_SWEEP_MAP],
current_.scopes[Scope::MC_SWEEP_OLD],
current_.incremental_marking_duration,
current_.scopes[Scope::MC_INCREMENTAL_FINALIZE],
current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE],
current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_EPILOGUE],
current_.scopes[Scope::MC_INCREMENTAL_FINALIZE_OBJECT_GROUPING],
current_.scopes[Scope::MC_INCREMENTAL_WRAPPER_PROLOGUE],
current_.scopes[Scope::MC_INCREMENTAL_WRAPPER_TRACING],
current_.longest_incremental_marking_finalization_step,
current_.incremental_marking_finalizaton_steps,
current_.incremental_marking_steps,
current_.incremental_marking_duration,
current_.longest_incremental_marking_step,
cumulative_incremental_marking_finalization_steps_,
cumulative_incremental_marking_finalization_duration_,
longest_incremental_marking_finalization_step_,
IncrementalMarkingSpeedInBytesPerMillisecond(),
current_.start_object_size, current_.end_object_size,
current_.start_holes_size, current_.end_holes_size,
......
......@@ -9,6 +9,7 @@
#include "src/base/platform/platform.h"
#include "src/counters.h"
#include "src/globals.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
namespace v8 {
namespace internal {
......@@ -59,54 +60,64 @@ inline BytesAndDuration MakeBytesAndDuration(uint64_t bytes, double duration) {
enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects };
#define TRACER_SCOPES(F) \
F(EXTERNAL_WEAK_GLOBAL_HANDLES) \
F(MC_CLEAR) \
F(MC_CLEAR_CODE_FLUSH) \
F(MC_CLEAR_DEPENDENT_CODE) \
F(MC_CLEAR_GLOBAL_HANDLES) \
F(MC_CLEAR_MAPS) \
F(MC_CLEAR_SLOTS_BUFFER) \
F(MC_CLEAR_STORE_BUFFER) \
F(MC_CLEAR_STRING_TABLE) \
F(MC_CLEAR_WEAK_CELLS) \
F(MC_CLEAR_WEAK_COLLECTIONS) \
F(MC_CLEAR_WEAK_LISTS) \
F(MC_EVACUATE) \
F(MC_EVACUATE_CANDIDATES) \
F(MC_EVACUATE_CLEAN_UP) \
F(MC_EVACUATE_COPY) \
F(MC_EVACUATE_UPDATE_POINTERS) \
F(MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED) \
F(MC_EVACUATE_UPDATE_POINTERS_TO_NEW) \
F(MC_EVACUATE_UPDATE_POINTERS_WEAK) \
F(MC_EXTERNAL_EPILOGUE) \
F(MC_EXTERNAL_PROLOGUE) \
F(MC_FINISH) \
F(MC_INCREMENTAL_FINALIZE) \
F(MC_INCREMENTAL_EXTERNAL_EPILOGUE) \
F(MC_INCREMENTAL_EXTERNAL_PROLOGUE) \
F(MC_MARK) \
F(MC_MARK_FINISH_INCREMENTAL) \
F(MC_MARK_PREPARE_CODE_FLUSH) \
F(MC_MARK_ROOTS) \
F(MC_MARK_WEAK_CLOSURE) \
F(MC_MARK_WEAK_CLOSURE_EPHEMERAL) \
F(MC_MARK_WEAK_CLOSURE_WEAK_HANDLES) \
F(MC_MARK_WEAK_CLOSURE_WEAK_ROOTS) \
F(MC_MARK_WEAK_CLOSURE_HARMONY) \
F(MC_SWEEP) \
F(MC_SWEEP_CODE) \
F(MC_SWEEP_MAP) \
F(MC_SWEEP_OLD) \
F(SCAVENGER_CODE_FLUSH_CANDIDATES) \
F(SCAVENGER_EXTERNAL_EPILOGUE) \
F(SCAVENGER_EXTERNAL_PROLOGUE) \
F(SCAVENGER_OBJECT_GROUPS) \
F(SCAVENGER_OLD_TO_NEW_POINTERS) \
F(SCAVENGER_ROOTS) \
F(SCAVENGER_SCAVENGE) \
F(SCAVENGER_SEMISPACE) \
#define INCREMENTAL_SCOPES(F) \
F(MC_INCREMENTAL_WRAPPER_PROLOGUE) \
F(MC_INCREMENTAL_WRAPPER_TRACING) \
F(MC_INCREMENTAL_FINALIZE) \
F(MC_INCREMENTAL_FINALIZE_OBJECT_GROUPING) \
F(MC_INCREMENTAL_EXTERNAL_EPILOGUE) \
F(MC_INCREMENTAL_EXTERNAL_PROLOGUE)
#define TRACER_SCOPES(F) \
INCREMENTAL_SCOPES(F) \
F(EXTERNAL_WEAK_GLOBAL_HANDLES) \
F(MC_CLEAR) \
F(MC_CLEAR_CODE_FLUSH) \
F(MC_CLEAR_DEPENDENT_CODE) \
F(MC_CLEAR_GLOBAL_HANDLES) \
F(MC_CLEAR_MAPS) \
F(MC_CLEAR_SLOTS_BUFFER) \
F(MC_CLEAR_STORE_BUFFER) \
F(MC_CLEAR_STRING_TABLE) \
F(MC_CLEAR_WEAK_CELLS) \
F(MC_CLEAR_WEAK_COLLECTIONS) \
F(MC_CLEAR_WEAK_LISTS) \
F(MC_EVACUATE) \
F(MC_EVACUATE_CANDIDATES) \
F(MC_EVACUATE_CLEAN_UP) \
F(MC_EVACUATE_COPY) \
F(MC_EVACUATE_UPDATE_POINTERS) \
F(MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED) \
F(MC_EVACUATE_UPDATE_POINTERS_TO_NEW) \
F(MC_EVACUATE_UPDATE_POINTERS_WEAK) \
F(MC_EXTERNAL_EPILOGUE) \
F(MC_EXTERNAL_PROLOGUE) \
F(MC_FINISH) \
F(MC_MARK) \
F(MC_MARK_FINISH_INCREMENTAL) \
F(MC_MARK_PREPARE_CODE_FLUSH) \
F(MC_MARK_ROOTS) \
F(MC_MARK_WEAK_CLOSURE) \
F(MC_MARK_WEAK_CLOSURE_EPHEMERAL) \
F(MC_MARK_WEAK_CLOSURE_WEAK_HANDLES) \
F(MC_MARK_WEAK_CLOSURE_WEAK_ROOTS) \
F(MC_MARK_WEAK_CLOSURE_HARMONY) \
F(MC_MARK_WRAPPER_EPILOGUE) \
F(MC_MARK_WRAPPER_PROLOGUE) \
F(MC_MARK_WRAPPER_TRACING) \
F(MC_MARK_OBJECT_GROUPING) \
F(MC_SWEEP) \
F(MC_SWEEP_CODE) \
F(MC_SWEEP_MAP) \
F(MC_SWEEP_OLD) \
F(SCAVENGER_CODE_FLUSH_CANDIDATES) \
F(SCAVENGER_EXTERNAL_EPILOGUE) \
F(SCAVENGER_EXTERNAL_PROLOGUE) \
F(SCAVENGER_OBJECT_GROUPS) \
F(SCAVENGER_OLD_TO_NEW_POINTERS) \
F(SCAVENGER_ROOTS) \
F(SCAVENGER_SCAVENGE) \
F(SCAVENGER_SEMISPACE) \
F(SCAVENGER_WEAK)
#define TRACE_GC(tracer, scope_id) \
......@@ -126,7 +137,12 @@ class GCTracer {
#define DEFINE_SCOPE(scope) scope,
TRACER_SCOPES(DEFINE_SCOPE)
#undef DEFINE_SCOPE
NUMBER_OF_SCOPES
NUMBER_OF_SCOPES,
FIRST_INCREMENTAL_SCOPE = MC_INCREMENTAL_WRAPPER_PROLOGUE,
LAST_INCREMENTAL_SCOPE = MC_INCREMENTAL_EXTERNAL_PROLOGUE,
NUMBER_OF_INCREMENTAL_SCOPES =
LAST_INCREMENTAL_SCOPE - FIRST_INCREMENTAL_SCOPE + 1
};
Scope(GCTracer* tracer, ScopeId scope);
......@@ -197,7 +213,7 @@ class GCTracer {
// Size of new space objects in constructor.
intptr_t new_space_object_size;
// Size of survived new space objects in desctructor.
// Size of survived new space objects in destructor.
intptr_t survived_new_space_object_size;
// Number of incremental marking steps since creation of tracer.
......@@ -239,10 +255,35 @@ class GCTracer {
// events
double pure_incremental_marking_duration;
// Longest incremental marking step since start of marking.
// (value at start of event)
// Longest incremental marking step since start of marking (start of event).
double longest_incremental_marking_step;
// Number of incremental marking finalization steps since creation of
// tracer.
int cumulative_incremental_marking_finalization_steps;
// Cumulative pure duration of incremental marking steps since creation of
// tracer. (value at start of event)
double cumulative_incremental_marking_finalizaton_duration;
// Longest incremental marking finalization step since start of marking
// (start of event).
double longest_incremental_marking_finalization_step;
// Incremental marking finalization steps since
// - last event for SCAVENGER events
// - last INCREMENTAL_MARK_COMPACTOR event for INCREMENTAL_MARK_COMPACTOR
// events
int incremental_marking_finalizaton_steps;
// Duration of incremental marking finalization steps since
// - last event for SCAVENGER events
// - last INCREMENTAL_MARK_COMPACTOR event for INCREMENTAL_MARK_COMPACTOR
// events
double incremental_marking_finalization_duration;
double cumulative_incremental_scopes[Scope::NUMBER_OF_INCREMENTAL_SCOPES];
// Amounts of time spent in different scopes during GC.
double scopes[Scope::NUMBER_OF_SCOPES];
};
......@@ -365,6 +406,17 @@ class GCTracer {
// Discard all recorded survival events.
void ResetSurvivalEvents();
void AddScopeSample(Scope::ScopeId scope, double duration);
private:
FRIEND_TEST(GCTracer, AverageSpeed);
FRIEND_TEST(GCTracerTest, AllocationThroughput);
FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughput);
FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughputWithProvidedTime);
FRIEND_TEST(GCTracerTest, OldGenerationAllocationThroughputWithProvidedTime);
FRIEND_TEST(GCTracerTest, RegularScope);
FRIEND_TEST(GCTracerTest, IncrementalScope);
// 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.
......@@ -374,7 +426,6 @@ class GCTracer {
void ResetForTesting();
private:
// Print one detailed trace line in name=value format.
// TODO(ernstm): Move to Heap.
void PrintNVP() const;
......@@ -455,6 +506,10 @@ class GCTracer {
// This timer is precise when run with --print-cumulative-gc-stat
double cumulative_marking_duration_;
// Cumulative duration of incremental marking scopes since the creation of
// the tracer.
double cumulative_incremental_scopes_[Scope::NUMBER_OF_INCREMENTAL_SCOPES];
// Total sweeping time on the main thread.
// This timer is precise when run with --print-cumulative-gc-stat
// TODO(hpayer): Account for sweeping time on sweeper threads. Add a
......
......@@ -557,6 +557,8 @@ void IncrementalMarking::StartMarking() {
state_ = MARKING;
if (heap_->UsingEmbedderHeapTracer()) {
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_INCREMENTAL_WRAPPER_PROLOGUE);
heap_->mark_compact_collector()->embedder_heap_tracer()->TracePrologue();
}
......@@ -622,6 +624,9 @@ void IncrementalMarking::MarkRoots() {
void IncrementalMarking::MarkObjectGroups() {
TRACE_GC(heap_->tracer(),
GCTracer::Scope::MC_INCREMENTAL_FINALIZE_OBJECT_GROUPING);
DCHECK(!heap_->UsingEmbedderHeapTracer());
DCHECK(!finalize_marking_completed_);
DCHECK(IsMarking());
......@@ -1203,6 +1208,8 @@ intptr_t IncrementalMarking::Step(intptr_t allocated_bytes,
bytes_processed = ProcessMarkingDeque(bytes_to_process);
if (FLAG_incremental_marking_wrappers &&
heap_->UsingEmbedderHeapTracer()) {
TRACE_GC(heap()->tracer(),
GCTracer::Scope::MC_INCREMENTAL_WRAPPER_TRACING);
// This currently marks through all registered wrappers and does not
// respect bytes_to_process.
// TODO(hpayer): Integrate incremental marking of wrappers into
......
......@@ -814,6 +814,7 @@ void MarkCompactCollector::Prepare() {
if (!was_marked_incrementally_) {
if (heap_->UsingEmbedderHeapTracer()) {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_PROLOGUE);
heap_->mark_compact_collector()->embedder_heap_tracer()->TracePrologue();
}
}
......@@ -2081,12 +2082,14 @@ void MarkCompactCollector::ProcessEphemeralMarking(
bool work_to_do = true;
while (work_to_do) {
if (UsingEmbedderHeapTracer()) {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_TRACING);
RegisterWrappersWithEmbedderHeapTracer();
embedder_heap_tracer()->AdvanceTracing(
0, EmbedderHeapTracer::AdvanceTracingActions(
EmbedderHeapTracer::ForceCompletionAction::FORCE_COMPLETION));
}
if (!only_process_harmony_weak_collections) {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_OBJECT_GROUPING);
isolate()->global_handles()->IterateObjectGroups(
visitor, &IsUnmarkedHeapObjectWithHeap);
MarkImplicitRefGroups(&MarkCompactMarkingVisitor::MarkObject);
......@@ -2365,6 +2368,7 @@ void MarkCompactCollector::MarkLiveObjects() {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WEAK_CLOSURE_HARMONY);
ProcessEphemeralMarking(&root_visitor, true);
if (UsingEmbedderHeapTracer()) {
TRACE_GC(heap()->tracer(), GCTracer::Scope::MC_MARK_WRAPPER_EPILOGUE);
embedder_heap_tracer()->TraceEpilogue();
}
}
......
......@@ -6206,54 +6206,6 @@ TEST(OldSpaceAllocationCounter) {
}
TEST(NewSpaceAllocationThroughput) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
GCTracer* tracer = heap->tracer();
tracer->ResetForTesting();
int time1 = 100;
size_t counter1 = 1000;
tracer->SampleAllocation(time1, counter1, 0);
int time2 = 200;
size_t counter2 = 2000;
tracer->SampleAllocation(time2, counter2, 0);
size_t throughput =
tracer->NewSpaceAllocationThroughputInBytesPerMillisecond();
CHECK_EQ((counter2 - counter1) / (time2 - time1), throughput);
int time3 = 1000;
size_t counter3 = 30000;
tracer->SampleAllocation(time3, counter3, 0);
throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond();
CHECK_EQ((counter3 - counter1) / (time3 - time1), throughput);
}
TEST(NewSpaceAllocationThroughput2) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
GCTracer* tracer = heap->tracer();
tracer->ResetForTesting();
int time1 = 100;
size_t counter1 = 1000;
tracer->SampleAllocation(time1, counter1, 0);
int time2 = 200;
size_t counter2 = 2000;
tracer->SampleAllocation(time2, counter2, 0);
size_t throughput =
tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(100);
CHECK_EQ((counter2 - counter1) / (time2 - time1), throughput);
int time3 = 1000;
size_t counter3 = 30000;
tracer->SampleAllocation(time3, counter3, 0);
throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(100);
CHECK_EQ((counter3 - counter1) / (time3 - time1), throughput);
}
static void CheckLeak(const v8::FunctionCallbackInfo<v8::Value>& args) {
Isolate* isolate = CcTest::i_isolate();
Object* message =
......@@ -6366,55 +6318,6 @@ TEST(RemoveCodeFromSharedFunctionInfoButNotFromClosure) {
"check(g1, g2);");
}
TEST(OldGenerationAllocationThroughput) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
GCTracer* tracer = heap->tracer();
tracer->ResetForTesting();
int time1 = 100;
size_t counter1 = 1000;
tracer->SampleAllocation(time1, 0, counter1);
int time2 = 200;
size_t counter2 = 2000;
tracer->SampleAllocation(time2, 0, counter2);
size_t throughput = static_cast<size_t>(
tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(100));
CHECK_EQ((counter2 - counter1) / (time2 - time1), throughput);
int time3 = 1000;
size_t counter3 = 30000;
tracer->SampleAllocation(time3, 0, counter3);
throughput = static_cast<size_t>(
tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(100));
CHECK_EQ((counter3 - counter1) / (time3 - time1), throughput);
}
TEST(AllocationThroughput) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
Isolate* isolate = CcTest::i_isolate();
Heap* heap = isolate->heap();
GCTracer* tracer = heap->tracer();
tracer->ResetForTesting();
int time1 = 100;
size_t counter1 = 1000;
tracer->SampleAllocation(time1, counter1, counter1);
int time2 = 200;
size_t counter2 = 2000;
tracer->SampleAllocation(time2, counter2, counter2);
size_t throughput = static_cast<size_t>(
tracer->AllocationThroughputInBytesPerMillisecond(100));
CHECK_EQ(2 * (counter2 - counter1) / (time2 - time1), throughput);
int time3 = 1000;
size_t counter3 = 30000;
tracer->SampleAllocation(time3, counter3, counter3);
throughput = tracer->AllocationThroughputInBytesPerMillisecond(100);
CHECK_EQ(2 * (counter3 - counter1) / (time3 - time1), throughput);
}
TEST(ContextMeasure) {
CcTest::InitializeVM();
v8::HandleScope scope(CcTest::isolate());
......
......@@ -5,12 +5,17 @@
#include <cmath>
#include <limits>
#include "src/globals.h"
#include "src/heap/gc-tracer.h"
#include "src/isolate.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
typedef TestWithContext GCTracerTest;
TEST(GCTracer, AverageSpeed) {
RingBuffer<BytesAndDuration> buffer;
EXPECT_EQ(100 / 2,
......@@ -45,5 +50,141 @@ TEST(GCTracer, AverageSpeed) {
GCTracer::AverageSpeed(buffer, MakeBytesAndDuration(0, 0), buffer.kSize));
}
namespace {
void SampleAndAddAllocaton(v8::internal::GCTracer* tracer, double time_ms,
size_t new_space_counter_bytes,
size_t old_generation_counter_bytes) {
tracer->SampleAllocation(time_ms, new_space_counter_bytes,
old_generation_counter_bytes);
tracer->AddAllocation(time_ms);
}
} // namespace
TEST_F(GCTracerTest, AllocationThroughput) {
GCTracer* tracer = i_isolate()->heap()->tracer();
tracer->ResetForTesting();
int time1 = 100;
size_t counter1 = 1000;
// First sample creates baseline but is not part of the recorded samples.
tracer->SampleAllocation(time1, counter1, counter1);
SampleAndAddAllocaton(tracer, time1, counter1, counter1);
int time2 = 200;
size_t counter2 = 2000;
SampleAndAddAllocaton(tracer, time2, counter2, counter2);
// Will only consider the current sample.
size_t throughput = static_cast<size_t>(
tracer->AllocationThroughputInBytesPerMillisecond(100));
EXPECT_EQ(2 * (counter2 - counter1) / (time2 - time1), throughput);
int time3 = 1000;
size_t counter3 = 30000;
SampleAndAddAllocaton(tracer, time3, counter3, counter3);
// Considers last 2 samples.
throughput = tracer->AllocationThroughputInBytesPerMillisecond(801);
EXPECT_EQ(2 * (counter3 - counter1) / (time3 - time1), throughput);
}
TEST_F(GCTracerTest, NewSpaceAllocationThroughput) {
GCTracer* tracer = i_isolate()->heap()->tracer();
tracer->ResetForTesting();
int time1 = 100;
size_t counter1 = 1000;
SampleAndAddAllocaton(tracer, time1, counter1, 0);
int time2 = 200;
size_t counter2 = 2000;
SampleAndAddAllocaton(tracer, time2, counter2, 0);
size_t throughput =
tracer->NewSpaceAllocationThroughputInBytesPerMillisecond();
EXPECT_EQ((counter2 - counter1) / (time2 - time1), throughput);
int time3 = 1000;
size_t counter3 = 30000;
SampleAndAddAllocaton(tracer, time3, counter3, 0);
throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond();
EXPECT_EQ((counter3 - counter1) / (time3 - time1), throughput);
}
TEST_F(GCTracerTest, NewSpaceAllocationThroughputWithProvidedTime) {
GCTracer* tracer = i_isolate()->heap()->tracer();
tracer->ResetForTesting();
int time1 = 100;
size_t counter1 = 1000;
// First sample creates baseline but is not part of the recorded samples.
SampleAndAddAllocaton(tracer, time1, counter1, 0);
int time2 = 200;
size_t counter2 = 2000;
SampleAndAddAllocaton(tracer, time2, counter2, 0);
// Will only consider the current sample.
size_t throughput =
tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(100);
EXPECT_EQ((counter2 - counter1) / (time2 - time1), throughput);
int time3 = 1000;
size_t counter3 = 30000;
SampleAndAddAllocaton(tracer, time3, counter3, 0);
// Considers last 2 samples.
throughput = tracer->NewSpaceAllocationThroughputInBytesPerMillisecond(801);
EXPECT_EQ((counter3 - counter1) / (time3 - time1), throughput);
}
TEST_F(GCTracerTest, OldGenerationAllocationThroughputWithProvidedTime) {
GCTracer* tracer = i_isolate()->heap()->tracer();
tracer->ResetForTesting();
int time1 = 100;
size_t counter1 = 1000;
// First sample creates baseline but is not part of the recorded samples.
SampleAndAddAllocaton(tracer, time1, 0, counter1);
int time2 = 200;
size_t counter2 = 2000;
SampleAndAddAllocaton(tracer, time2, 0, counter2);
// Will only consider the current sample.
size_t throughput = static_cast<size_t>(
tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(100));
EXPECT_EQ((counter2 - counter1) / (time2 - time1), throughput);
int time3 = 1000;
size_t counter3 = 30000;
SampleAndAddAllocaton(tracer, time3, 0, counter3);
// Considers last 2 samples.
throughput = static_cast<size_t>(
tracer->OldGenerationAllocationThroughputInBytesPerMillisecond(801));
EXPECT_EQ((counter3 - counter1) / (time3 - time1), throughput);
}
TEST_F(GCTracerTest, RegularScope) {
GCTracer* tracer = i_isolate()->heap()->tracer();
{
// Sample not added because it's not within a started tracer.
tracer->AddScopeSample(GCTracer::Scope::MC_MARK, 100);
}
tracer->Start(MARK_COMPACTOR, "gc unittest", "collector unittest");
{ tracer->AddScopeSample(GCTracer::Scope::MC_MARK, 100); }
tracer->Stop(MARK_COMPACTOR);
EXPECT_EQ(
static_cast<size_t>(tracer->current_.scopes[GCTracer::Scope::MC_MARK]),
100u);
}
TEST_F(GCTracerTest, IncrementalScope) {
GCTracer* tracer = i_isolate()->heap()->tracer();
{
// Sample is added because its ScopeId is listed as incremental sample.
tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 100);
}
tracer->Start(MARK_COMPACTOR, "gc unittest", "collector unittest");
// Switch to incremental MC to enable writing back incremental scopes.
tracer->current_.type = GCTracer::Event::INCREMENTAL_MARK_COMPACTOR;
{ tracer->AddScopeSample(GCTracer::Scope::MC_INCREMENTAL_FINALIZE, 100); }
tracer->Stop(MARK_COMPACTOR);
EXPECT_EQ(
static_cast<size_t>(
tracer->current_.scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]),
200u);
}
} // 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