gc-idle-time-handler.cc 4.41 KB
Newer Older
1 2 3 4 5
// Copyright 2014 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/heap/gc-idle-time-handler.h"
6 7

#include "src/flags.h"
8 9
#include "src/heap/gc-tracer.h"
#include "src/utils.h"
10 11 12 13 14

namespace v8 {
namespace internal {

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
void GCIdleTimeHeapState::Print() {
21 22
  PrintF("contexts_disposed=%d ", contexts_disposed);
  PrintF("contexts_disposal_rate=%f ", contexts_disposal_rate);
23
  PrintF("size_of_objects=%zu ", size_of_objects);
24 25 26
  PrintF("incremental_marking_stopped=%d ", incremental_marking_stopped);
}

27
size_t GCIdleTimeHandler::EstimateMarkingStepSize(
28
    double idle_time_in_ms, double marking_speed_in_bytes_per_ms) {
29
  DCHECK_LT(0, idle_time_in_ms);
30 31

  if (marking_speed_in_bytes_per_ms == 0) {
32
    marking_speed_in_bytes_per_ms = kInitialConservativeMarkingSpeed;
33 34
  }

35 36
  double marking_step_size = marking_speed_in_bytes_per_ms * idle_time_in_ms;
  if (marking_step_size >= kMaximumMarkingStepSize) {
37
    return kMaximumMarkingStepSize;
38
  }
39
  return static_cast<size_t>(marking_step_size * kConservativeTimeRatio);
40
}
41

42
double GCIdleTimeHandler::EstimateFinalIncrementalMarkCompactTime(
43
    size_t size_of_objects,
44
    double final_incremental_mark_compact_speed_in_bytes_per_ms) {
45 46 47 48
  if (final_incremental_mark_compact_speed_in_bytes_per_ms == 0) {
    final_incremental_mark_compact_speed_in_bytes_per_ms =
        kInitialConservativeFinalIncrementalMarkCompactSpeed;
  }
49
  double result =
50
      size_of_objects / final_incremental_mark_compact_speed_in_bytes_per_ms;
51
  return Min<double>(result, kMaxFinalIncrementalMarkCompactTimeInMs);
52 53
}

54
bool GCIdleTimeHandler::ShouldDoContextDisposalMarkCompact(
55 56
    int contexts_disposed, double contexts_disposal_rate,
    size_t size_of_objects) {
57
  return contexts_disposed > 0 && contexts_disposal_rate > 0 &&
58 59
         contexts_disposal_rate < kHighContextDisposalRate &&
         size_of_objects <= kMaxHeapSizeForContextDisposalMarkCompact;
60 61
}

62
bool GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
63 64
    double idle_time_in_ms, size_t size_of_objects,
    double final_incremental_mark_compact_speed_in_bytes_per_ms) {
65 66 67 68 69 70
  return idle_time_in_ms >=
         EstimateFinalIncrementalMarkCompactTime(
             size_of_objects,
             final_incremental_mark_compact_speed_in_bytes_per_ms);
}

71
bool GCIdleTimeHandler::ShouldDoOverApproximateWeakClosure(
72
    double idle_time_in_ms) {
73 74 75 76 77
  // TODO(jochen): Estimate the time it will take to build the object groups.
  return idle_time_in_ms >= kMinTimeForOverApproximatingWeakClosureInMs;
}


78
// The following logic is implemented by the controller:
79 80 81
// (1) If we don't have any idle time, do nothing, unless a context was
// disposed, incremental marking is stopped, and the heap is small. Then do
// a full GC.
82 83
// (2) If the context disposal rate is high and we cannot perform a full GC,
// we do nothing until the context disposal rate becomes lower.
84
// (3) If the new space is almost full and we can afford a scavenge or if the
85
// next scavenge will very likely take long, then a scavenge is performed.
86
// (4) If sweeping is in progress and we received a large enough idle time
87
// request, we finalize sweeping here.
88
// (5) If incremental marking is in progress, we perform a marking step. Note,
89
// that this currently may trigger a full garbage collection.
90
GCIdleTimeAction GCIdleTimeHandler::Compute(double idle_time_in_ms,
91
                                            GCIdleTimeHeapState heap_state) {
92
  if (static_cast<int>(idle_time_in_ms) <= 0) {
93
    if (heap_state.incremental_marking_stopped) {
94 95 96
      if (ShouldDoContextDisposalMarkCompact(heap_state.contexts_disposed,
                                             heap_state.contexts_disposal_rate,
                                             heap_state.size_of_objects)) {
97
        return GCIdleTimeAction::kFullGC;
98 99
      }
    }
100
    return GCIdleTimeAction::kDone;
101 102
  }

103 104
  if (FLAG_incremental_marking && !heap_state.incremental_marking_stopped) {
    return GCIdleTimeAction::kIncrementalStep;
105
  }
106

107
  return GCIdleTimeAction::kDone;
108 109
}

110
bool GCIdleTimeHandler::Enabled() { return FLAG_incremental_marking; }
111

112 113
}  // namespace internal
}  // namespace v8