LCOV - code coverage report
Current view: top level - src/heap - gc-idle-time-handler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 19 47 40.4 %
Date: 2019-02-19 Functions: 6 12 50.0 %

          Line data    Source code
       1             : // Copyright 2014 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/heap/gc-idle-time-handler.h"
       6             : 
       7             : #include "src/flags.h"
       8             : #include "src/heap/gc-tracer.h"
       9             : #include "src/utils.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14             : const double GCIdleTimeHandler::kConservativeTimeRatio = 0.9;
      15             : const size_t GCIdleTimeHandler::kMaxFinalIncrementalMarkCompactTimeInMs = 1000;
      16             : const double GCIdleTimeHandler::kHighContextDisposalRate = 100;
      17             : const size_t GCIdleTimeHandler::kMinTimeForOverApproximatingWeakClosureInMs = 1;
      18             : 
      19             : 
      20           0 : void GCIdleTimeAction::Print() {
      21           0 :   switch (type) {
      22             :     case DONE:
      23           0 :       PrintF("done");
      24           0 :       break;
      25             :     case DO_NOTHING:
      26           0 :       PrintF("no action");
      27           0 :       break;
      28             :     case DO_INCREMENTAL_STEP:
      29           0 :       PrintF("incremental step");
      30           0 :       if (additional_work) {
      31           0 :         PrintF("; finalized marking");
      32             :       }
      33             :       break;
      34             :     case DO_FULL_GC:
      35           0 :       PrintF("full GC");
      36           0 :       break;
      37             :   }
      38           0 : }
      39             : 
      40             : 
      41           0 : void GCIdleTimeHeapState::Print() {
      42           0 :   PrintF("contexts_disposed=%d ", contexts_disposed);
      43           0 :   PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate);
      44           0 :   PrintF("size_of_objects=%" PRIuS " ", size_of_objects);
      45           0 :   PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped);
      46           0 : }
      47             : 
      48     1073348 : size_t GCIdleTimeHandler::EstimateMarkingStepSize(
      49             :     double idle_time_in_ms, double marking_speed_in_bytes_per_ms) {
      50             :   DCHECK_LT(0, idle_time_in_ms);
      51             : 
      52     1073348 :   if (marking_speed_in_bytes_per_ms == 0) {
      53             :     marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed;
      54             :   }
      55             : 
      56     1073348 :   double marking_step_size = marking_speed_in_bytes_per_ms * idle_time_in_ms;
      57     1073348 :   if (marking_step_size >= kMaximumMarkingStepSize) {
      58             :     return kMaximumMarkingStepSize;
      59             :   }
      60     1073346 :   return static_cast<size_t>(marking_step_size * kConservativeTimeRatio);
      61             : }
      62             : 
      63           0 : double GCIdleTimeHandler::EstimateFinalIncrementalMarkCompactTime(
      64             :     size_t size_of_objects,
      65             :     double final_incremental_mark_compact_speed_in_bytes_per_ms) {
      66           2 :   if (final_incremental_mark_compact_speed_in_bytes_per_ms == 0) {
      67             :     final_incremental_mark_compact_speed_in_bytes_per_ms =
      68             :         kInitialConservativeFinalIncrementalMarkCompactSpeed;
      69             :   }
      70             :   double result =
      71           2 :       size_of_objects / final_incremental_mark_compact_speed_in_bytes_per_ms;
      72           0 :   return Min<double>(result, kMaxFinalIncrementalMarkCompactTimeInMs);
      73             : }
      74             : 
      75           0 : bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact(
      76             :     int contexts_disposed, double contexts_disposal_rate,
      77             :     size_t size_of_objects) {
      78         412 :   return contexts_disposed > 0 && contexts_disposal_rate > 0 &&
      79         745 :          contexts_disposal_rate < kHighContextDisposalRate &&
      80           0 :          size_of_objects <= kMaxHeapSizeForContextDisposalMarkCompact;
      81             : }
      82             : 
      83           2 : bool GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
      84             :     double idle_time_in_ms, size_t size_of_objects,
      85             :     double final_incremental_mark_compact_speed_in_bytes_per_ms) {
      86             :   return idle_time_in_ms >=
      87             :          EstimateFinalIncrementalMarkCompactTime(
      88             :              size_of_objects,
      89           2 :              final_incremental_mark_compact_speed_in_bytes_per_ms);
      90             : }
      91             : 
      92           0 : bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure(
      93             :     double idle_time_in_ms) {
      94             :   // TODO(jochen): Estimate the time it will take to build the object groups.
      95           0 :   return idle_time_in_ms >= kMinTimeForOverApproximatingWeakClosureInMs;
      96             : }
      97             : 
      98             : 
      99           0 : GCIdleTimeAction GCIdleTimeHandler::NothingOrDone(double idle_time_in_ms) {
     100           0 :   if (idle_time_in_ms >= kMinBackgroundIdleTime) {
     101             :     return GCIdleTimeAction::Nothing();
     102             :   }
     103           0 :   if (idle_times_which_made_no_progress_ >= kMaxNoProgressIdleTimes) {
     104             :     return GCIdleTimeAction::Done();
     105             :   } else {
     106           0 :     idle_times_which_made_no_progress_++;
     107             :     return GCIdleTimeAction::Nothing();
     108             :   }
     109             : }
     110             : 
     111             : 
     112             : // The following logic is implemented by the controller:
     113             : // (1) If we don't have any idle time, do nothing, unless a context was
     114             : // disposed, incremental marking is stopped, and the heap is small. Then do
     115             : // a full GC.
     116             : // (2) If the context disposal rate is high and we cannot perform a full GC,
     117             : // we do nothing until the context disposal rate becomes lower.
     118             : // (3) If the new space is almost full and we can afford a scavenge or if the
     119             : // next scavenge will very likely take long, then a scavenge is performed.
     120             : // (4) If sweeping is in progress and we received a large enough idle time
     121             : // request, we finalize sweeping here.
     122             : // (5) If incremental marking is in progress, we perform a marking step. Note,
     123             : // that this currently may trigger a full garbage collection.
     124         691 : GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
     125             :                                             GCIdleTimeHeapState heap_state) {
     126         691 :   if (static_cast<int>(idle_time_in_ms) <= 0) {
     127         401 :     if (heap_state.incremental_marking_stopped) {
     128         268 :       if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed,
     129             :                                              heap_state.contexts_disposal_rate,
     130             :                                              heap_state.size_of_objects)) {
     131             :         return GCIdleTimeAction::FullGC();
     132             :       }
     133             :     }
     134             :     return GCIdleTimeAction::Nothing();
     135             :   }
     136             : 
     137             :   // We are in a context disposal GC scenario. Don't do anything if we do not
     138             :   // get the right idle signal.
     139         290 :   if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed,
     140             :                                          heap_state.contexts_disposal_rate,
     141             :                                          heap_state.size_of_objects)) {
     142             :     return NothingOrDone(idle_time_in_ms);
     143             :   }
     144             : 
     145         290 :   if (!FLAG_incremental_marking || heap_state.incremental_marking_stopped) {
     146             :     return GCIdleTimeAction::Done();
     147             :   }
     148             : 
     149             :   return GCIdleTimeAction::IncrementalStep();
     150             : }
     151             : 
     152          13 : bool GCIdleTimeHandler::Enabled() { return FLAG_incremental_marking; }
     153             : 
     154             : }  // namespace internal
     155      178779 : }  // namespace v8

Generated by: LCOV version 1.10