diff options
Diffstat (limited to 'chromium/v8/src/heap')
-rw-r--r-- | chromium/v8/src/heap/gc-tracer.cc | 8 | ||||
-rw-r--r-- | chromium/v8/src/heap/gc-tracer.h | 7 | ||||
-rw-r--r-- | chromium/v8/src/heap/heap.cc | 122 | ||||
-rw-r--r-- | chromium/v8/src/heap/heap.h | 17 | ||||
-rw-r--r-- | chromium/v8/src/heap/incremental-marking.cc | 24 | ||||
-rw-r--r-- | chromium/v8/src/heap/incremental-marking.h | 23 |
6 files changed, 167 insertions, 34 deletions
diff --git a/chromium/v8/src/heap/gc-tracer.cc b/chromium/v8/src/heap/gc-tracer.cc index 214bb8b24d6..6728f09bdad 100644 --- a/chromium/v8/src/heap/gc-tracer.cc +++ b/chromium/v8/src/heap/gc-tracer.cc @@ -682,11 +682,15 @@ size_t GCTracer::AllocationThroughputInBytesPerMillisecond( } +size_t GCTracer::CurrentAllocationThroughputInBytesPerMillisecond() const { + return AllocationThroughputInBytesPerMillisecond(kThroughputTimeFrameMs); +} + + size_t GCTracer::CurrentOldGenerationAllocationThroughputInBytesPerMillisecond() const { - static const double kThroughputTimeFrame = 5000; return OldGenerationAllocationThroughputInBytesPerMillisecond( - kThroughputTimeFrame); + kThroughputTimeFrameMs); } diff --git a/chromium/v8/src/heap/gc-tracer.h b/chromium/v8/src/heap/gc-tracer.h index 468fc9c0be7..e26fc898f99 100644 --- a/chromium/v8/src/heap/gc-tracer.h +++ b/chromium/v8/src/heap/gc-tracer.h @@ -291,6 +291,8 @@ class GCTracer { typedef RingBuffer<SurvivalEvent, kRingBufferMaxSize> SurvivalEventBuffer; + static const int kThroughputTimeFrameMs = 5000; + explicit GCTracer(Heap* heap); // Start collecting data. @@ -408,6 +410,11 @@ class GCTracer { // Returns 0 if no allocation events have been recorded. size_t AllocationThroughputInBytesPerMillisecond(double time_ms) const; + // Allocation throughput in heap in bytes/milliseconds in + // the last five seconds. + // Returns 0 if no allocation events have been recorded. + size_t CurrentAllocationThroughputInBytesPerMillisecond() const; + // Allocation throughput in old generation in bytes/milliseconds in // the last five seconds. // Returns 0 if no allocation events have been recorded. diff --git a/chromium/v8/src/heap/heap.cc b/chromium/v8/src/heap/heap.cc index fc36be8041f..3d953730013 100644 --- a/chromium/v8/src/heap/heap.cc +++ b/chromium/v8/src/heap/heap.cc @@ -775,7 +775,8 @@ void Heap::PreprocessStackTraces() { void Heap::HandleGCRequest() { if (incremental_marking()->request_type() == IncrementalMarking::COMPLETE_MARKING) { - CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt"); + CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt", + incremental_marking()->CallbackFlags()); return; } DCHECK(FLAG_overapproximate_weak_closure); @@ -985,7 +986,7 @@ bool Heap::CollectGarbage(GarbageCollector collector, const char* gc_reason, if (!mark_compact_collector()->abort_incremental_marking() && incremental_marking()->IsStopped() && incremental_marking()->ShouldActivateEvenWithoutIdleNotification()) { - incremental_marking()->Start(kNoGCFlags); + incremental_marking()->Start(kNoGCFlags, kNoGCCallbackFlags, "GC epilogue"); } return next_gc_likely_to_collect_more; @@ -1012,9 +1013,18 @@ int Heap::NotifyContextDisposed(bool dependant_context) { } +void Heap::StartIncrementalMarking(int gc_flags, + const GCCallbackFlags gc_callback_flags, + const char* reason) { + DCHECK(incremental_marking()->IsStopped()); + incremental_marking()->Start(gc_flags, gc_callback_flags, reason); +} + + void Heap::StartIdleIncrementalMarking() { gc_idle_time_handler_.ResetNoProgressCounter(); - incremental_marking()->Start(kReduceMemoryFootprintMask); + StartIncrementalMarking(kReduceMemoryFootprintMask, kNoGCCallbackFlags, + "idle"); } @@ -4762,27 +4772,63 @@ void Heap::MakeHeapIterable() { } -bool Heap::HasLowYoungGenerationAllocationRate() { - const double high_mutator_utilization = 0.993; +static double ComputeMutatorUtilization(double mutator_speed, double gc_speed) { + const double kMinMutatorUtilization = 0.0; + const double kConservativeGcSpeedInBytesPerMillisecond = 200000; + if (mutator_speed == 0) return kMinMutatorUtilization; + if (gc_speed == 0) gc_speed = kConservativeGcSpeedInBytesPerMillisecond; + // Derivation: + // mutator_utilization = mutator_time / (mutator_time + gc_time) + // mutator_time = 1 / mutator_speed + // gc_time = 1 / gc_speed + // mutator_utilization = (1 / mutator_speed) / + // (1 / mutator_speed + 1 / gc_speed) + // mutator_utilization = gc_speed / (mutator_speed + gc_speed) + return gc_speed / (mutator_speed + gc_speed); +} + + +double Heap::YoungGenerationMutatorUtilization() { double mutator_speed = static_cast<double>( tracer()->NewSpaceAllocationThroughputInBytesPerMillisecond()); double gc_speed = static_cast<double>( tracer()->ScavengeSpeedInBytesPerMillisecond(kForSurvivedObjects)); - if (mutator_speed == 0 || gc_speed == 0) return false; - double mutator_utilization = gc_speed / (mutator_speed + gc_speed); - return mutator_utilization > high_mutator_utilization; + double result = ComputeMutatorUtilization(mutator_speed, gc_speed); + if (FLAG_trace_mutator_utilization) { + PrintIsolate(isolate(), + "Young generation mutator utilization = %.3f (" + "mutator_speed=%.f, gc_speed=%.f)\n", + result, mutator_speed, gc_speed); + } + return result; } -bool Heap::HasLowOldGenerationAllocationRate() { - const double high_mutator_utilization = 0.993; +double Heap::OldGenerationMutatorUtilization() { double mutator_speed = static_cast<double>( tracer()->OldGenerationAllocationThroughputInBytesPerMillisecond()); double gc_speed = static_cast<double>( tracer()->CombinedMarkCompactSpeedInBytesPerMillisecond()); - if (mutator_speed == 0 || gc_speed == 0) return false; - double mutator_utilization = gc_speed / (mutator_speed + gc_speed); - return mutator_utilization > high_mutator_utilization; + double result = ComputeMutatorUtilization(mutator_speed, gc_speed); + if (FLAG_trace_mutator_utilization) { + PrintIsolate(isolate(), + "Old generation mutator utilization = %.3f (" + "mutator_speed=%.f, gc_speed=%.f)\n", + result, mutator_speed, gc_speed); + } + return result; +} + + +bool Heap::HasLowYoungGenerationAllocationRate() { + const double high_mutator_utilization = 0.993; + return YoungGenerationMutatorUtilization() > high_mutator_utilization; +} + + +bool Heap::HasLowOldGenerationAllocationRate() { + const double high_mutator_utilization = 0.993; + return OldGenerationMutatorUtilization() > high_mutator_utilization; } @@ -4808,7 +4854,13 @@ bool Heap::HasHighFragmentation(intptr_t used, intptr_t committed) { void Heap::ReduceNewSpaceSize() { - if (!FLAG_predictable && HasLowAllocationRate()) { + // TODO(ulan): Unify this constant with the similar constant in + // GCIdleTimeHandler once the change is merged to 4.5. + static const size_t kLowAllocationThroughput = 1000; + size_t allocation_throughput = + tracer()->CurrentAllocationThroughputInBytesPerMillisecond(); + if (FLAG_predictable || allocation_throughput == 0) return; + if (allocation_throughput < kLowAllocationThroughput) { new_space_.Shrink(); UncommitFromSpace(); } @@ -4867,6 +4919,32 @@ GCIdleTimeHandler::HeapState Heap::ComputeHeapState() { } +double Heap::AdvanceIncrementalMarking( + intptr_t step_size_in_bytes, double deadline_in_ms, + IncrementalMarking::StepActions step_actions) { + DCHECK(!incremental_marking()->IsStopped()); + + if (step_size_in_bytes == 0) { + step_size_in_bytes = GCIdleTimeHandler::EstimateMarkingStepSize( + static_cast<size_t>(GCIdleTimeHandler::kIncrementalMarkingStepTimeInMs), + static_cast<size_t>( + tracer()->FinalIncrementalMarkCompactSpeedInBytesPerMillisecond())); + } + + double remaining_time_in_ms = 0.0; + do { + incremental_marking()->Step( + step_size_in_bytes, step_actions.completion_action, + step_actions.force_marking, step_actions.force_completion); + remaining_time_in_ms = deadline_in_ms - MonotonicallyIncreasingTimeInMs(); + } while (remaining_time_in_ms >= + 2.0 * GCIdleTimeHandler::kIncrementalMarkingStepTimeInMs && + !incremental_marking()->IsComplete() && + !mark_compact_collector_.marking_deque()->IsEmpty()); + return remaining_time_in_ms; +} + + bool Heap::PerformIdleTimeAction(GCIdleTimeAction action, GCIdleTimeHandler::HeapState heap_state, double deadline_in_ms) { @@ -4876,19 +4954,9 @@ bool Heap::PerformIdleTimeAction(GCIdleTimeAction action, result = true; break; case DO_INCREMENTAL_MARKING: { - DCHECK(!incremental_marking()->IsStopped()); - double remaining_idle_time_in_ms = 0.0; - do { - incremental_marking()->Step( - action.parameter, IncrementalMarking::NO_GC_VIA_STACK_GUARD, - IncrementalMarking::FORCE_MARKING, - IncrementalMarking::DO_NOT_FORCE_COMPLETION); - remaining_idle_time_in_ms = - deadline_in_ms - MonotonicallyIncreasingTimeInMs(); - } while (remaining_idle_time_in_ms >= - 2.0 * GCIdleTimeHandler::kIncrementalMarkingStepTimeInMs && - !incremental_marking()->IsComplete() && - !mark_compact_collector_.marking_deque()->IsEmpty()); + const double remaining_idle_time_in_ms = + AdvanceIncrementalMarking(action.parameter, deadline_in_ms, + IncrementalMarking::IdleStepActions()); if (remaining_idle_time_in_ms > 0.0) { action.additional_work = TryFinalizeIdleIncrementalMarking( remaining_idle_time_in_ms, heap_state.size_of_objects, diff --git a/chromium/v8/src/heap/heap.h b/chromium/v8/src/heap/heap.h index 6fb429ae7d6..4c9e3ad1448 100644 --- a/chromium/v8/src/heap/heap.h +++ b/chromium/v8/src/heap/heap.h @@ -837,6 +837,21 @@ class Heap { // incremental steps. void StartIdleIncrementalMarking(); + // Starts incremental marking assuming incremental marking is currently + // stopped. + void StartIncrementalMarking(int gc_flags, + const GCCallbackFlags gc_callback_flags, + const char* reason = nullptr); + + // Performs incremental marking steps of step_size_in_bytes as long as + // deadline_ins_ms is not reached. step_size_in_bytes can be 0 to compute + // an estimate increment. Returns the remaining time that cannot be used + // for incremental marking anymore because a single step would exceed the + // deadline. + double AdvanceIncrementalMarking( + intptr_t step_size_in_bytes, double deadline_in_ms, + IncrementalMarking::StepActions step_actions); + inline void increment_scan_on_scavenge_pages() { scan_on_scavenge_pages_++; if (FLAG_gc_verbose) { @@ -2267,6 +2282,8 @@ class Heap { bool HasLowYoungGenerationAllocationRate(); bool HasLowOldGenerationAllocationRate(); + double YoungGenerationMutatorUtilization(); + double OldGenerationMutatorUtilization(); void ReduceNewSpaceSize(); diff --git a/chromium/v8/src/heap/incremental-marking.cc b/chromium/v8/src/heap/incremental-marking.cc index 22051eaab2d..58eb0aa4097 100644 --- a/chromium/v8/src/heap/incremental-marking.cc +++ b/chromium/v8/src/heap/incremental-marking.cc @@ -16,22 +16,34 @@ namespace v8 { namespace internal { +IncrementalMarking::StepActions IncrementalMarking::IdleStepActions() { + return StepActions(IncrementalMarking::NO_GC_VIA_STACK_GUARD, + IncrementalMarking::FORCE_MARKING, + IncrementalMarking::DO_NOT_FORCE_COMPLETION); +} + + IncrementalMarking::IncrementalMarking(Heap* heap) : heap_(heap), state_(STOPPED), + is_compacting_(false), steps_count_(0), old_generation_space_available_at_start_of_incremental_(0), old_generation_space_used_at_start_of_incremental_(0), + bytes_rescanned_(0), should_hurry_(false), marking_speed_(0), + bytes_scanned_(0), allocated_(0), + write_barriers_invoked_since_last_step_(0), idle_marking_delay_counter_(0), no_marking_scope_depth_(0), unscanned_bytes_of_large_object_(0), was_activated_(false), weak_closure_was_overapproximated_(false), weak_closure_approximation_rounds_(0), - request_type_(COMPLETE_MARKING) {} + request_type_(COMPLETE_MARKING), + gc_callback_flags_(kNoGCCallbackFlags) {} void IncrementalMarking::RecordWriteSlow(HeapObject* obj, Object** slot, @@ -472,9 +484,12 @@ static void PatchIncrementalMarkingRecordWriteStubs( } -void IncrementalMarking::Start(int mark_compact_flags) { +void IncrementalMarking::Start(int mark_compact_flags, + const GCCallbackFlags gc_callback_flags, + const char* reason) { if (FLAG_trace_incremental_marking) { - PrintF("[IncrementalMarking] Start\n"); + PrintF("[IncrementalMarking] Start (%s)\n", + (reason == nullptr) ? "unknown reason" : reason); } DCHECK(FLAG_incremental_marking); DCHECK(FLAG_incremental_marking_steps); @@ -484,6 +499,7 @@ void IncrementalMarking::Start(int mark_compact_flags) { ResetStepCounters(); + gc_callback_flags_ = gc_callback_flags; was_activated_ = true; if (!heap_->mark_compact_collector()->sweeping_in_progress()) { @@ -826,7 +842,7 @@ void IncrementalMarking::Epilogue() { void IncrementalMarking::OldSpaceStep(intptr_t allocated) { if (IsStopped() && ShouldActivateEvenWithoutIdleNotification()) { - Start(Heap::kNoGCFlags); + Start(Heap::kNoGCFlags, kNoGCCallbackFlags, "old space step"); } else { Step(allocated * kFastMarking / kInitialMarkingSpeed, GC_VIA_STACK_GUARD); } diff --git a/chromium/v8/src/heap/incremental-marking.h b/chromium/v8/src/heap/incremental-marking.h index 8fe341154fa..706e3323270 100644 --- a/chromium/v8/src/heap/incremental-marking.h +++ b/chromium/v8/src/heap/incremental-marking.h @@ -26,6 +26,21 @@ class IncrementalMarking { enum GCRequestType { COMPLETE_MARKING, OVERAPPROXIMATION }; + struct StepActions { + StepActions(CompletionAction complete_action_, + ForceMarkingAction force_marking_, + ForceCompletionAction force_completion_) + : completion_action(complete_action_), + force_marking(force_marking_), + force_completion(force_completion_) {} + + CompletionAction completion_action; + ForceMarkingAction force_marking; + ForceCompletionAction force_completion; + }; + + static StepActions IdleStepActions(); + explicit IncrementalMarking(Heap* heap); static void Initialize(); @@ -67,7 +82,9 @@ class IncrementalMarking { bool WasActivated(); - void Start(int mark_compact_flags); + void Start(int mark_compact_flags, + const GCCallbackFlags gc_callback_flags = kNoGCCallbackFlags, + const char* reason = nullptr); void Stop(); @@ -185,6 +202,8 @@ class IncrementalMarking { Heap* heap() const { return heap_; } + GCCallbackFlags CallbackFlags() const { return gc_callback_flags_; } + private: int64_t SpaceLeftInOldSpace(); @@ -243,6 +262,8 @@ class IncrementalMarking { GCRequestType request_type_; + GCCallbackFlags gc_callback_flags_; + DISALLOW_IMPLICIT_CONSTRUCTORS(IncrementalMarking); }; } |