gc-idle-time-handler.h revision 958fae7ec3f466955f8e5b50fa5b8d38b9e91675
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#ifndef V8_HEAP_GC_IDLE_TIME_HANDLER_H_
6#define V8_HEAP_GC_IDLE_TIME_HANDLER_H_
7
8#include "src/globals.h"
9
10namespace v8 {
11namespace internal {
12
13enum GCIdleTimeActionType {
14  DONE,
15  DO_NOTHING,
16  DO_INCREMENTAL_MARKING,
17  DO_SCAVENGE,
18  DO_FULL_GC,
19  DO_FINALIZE_SWEEPING
20};
21
22
23class GCIdleTimeAction {
24 public:
25  static GCIdleTimeAction Done() {
26    GCIdleTimeAction result;
27    result.type = DONE;
28    result.parameter = 0;
29    result.additional_work = false;
30    return result;
31  }
32
33  static GCIdleTimeAction Nothing() {
34    GCIdleTimeAction result;
35    result.type = DO_NOTHING;
36    result.parameter = 0;
37    result.additional_work = false;
38    return result;
39  }
40
41  static GCIdleTimeAction IncrementalMarking(intptr_t step_size) {
42    GCIdleTimeAction result;
43    result.type = DO_INCREMENTAL_MARKING;
44    result.parameter = step_size;
45    result.additional_work = false;
46    return result;
47  }
48
49  static GCIdleTimeAction Scavenge() {
50    GCIdleTimeAction result;
51    result.type = DO_SCAVENGE;
52    result.parameter = 0;
53    result.additional_work = false;
54    return result;
55  }
56
57  static GCIdleTimeAction FullGC() {
58    GCIdleTimeAction result;
59    result.type = DO_FULL_GC;
60    result.parameter = 0;
61    result.additional_work = false;
62    return result;
63  }
64
65  static GCIdleTimeAction FinalizeSweeping() {
66    GCIdleTimeAction result;
67    result.type = DO_FINALIZE_SWEEPING;
68    result.parameter = 0;
69    result.additional_work = false;
70    return result;
71  }
72
73  void Print();
74
75  GCIdleTimeActionType type;
76  intptr_t parameter;
77  bool additional_work;
78};
79
80
81class GCTracer;
82
83// The idle time handler makes decisions about which garbage collection
84// operations are executing during IdleNotification.
85class GCIdleTimeHandler {
86 public:
87  // If we haven't recorded any incremental marking events yet, we carefully
88  // mark with a conservative lower bound for the marking speed.
89  static const size_t kInitialConservativeMarkingSpeed = 100 * KB;
90
91  // Maximum marking step size returned by EstimateMarkingStepSize.
92  static const size_t kMaximumMarkingStepSize = 700 * MB;
93
94  // We have to make sure that we finish the IdleNotification before
95  // idle_time_in_ms. Hence, we conservatively prune our workload estimate.
96  static const double kConservativeTimeRatio;
97
98  // If we haven't recorded any mark-compact events yet, we use
99  // conservative lower bound for the mark-compact speed.
100  static const size_t kInitialConservativeMarkCompactSpeed = 2 * MB;
101
102  // If we haven't recorded any final incremental mark-compact events yet, we
103  // use conservative lower bound for the mark-compact speed.
104  static const size_t kInitialConservativeFinalIncrementalMarkCompactSpeed =
105      2 * MB;
106
107  // Maximum mark-compact time returned by EstimateMarkCompactTime.
108  static const size_t kMaxMarkCompactTimeInMs;
109
110  // Maximum final incremental mark-compact time returned by
111  // EstimateFinalIncrementalMarkCompactTime.
112  static const size_t kMaxFinalIncrementalMarkCompactTimeInMs;
113
114  // Minimum time to finalize sweeping phase. The main thread may wait for
115  // sweeper threads.
116  static const size_t kMinTimeForFinalizeSweeping;
117
118  // Number of idle mark-compact events, after which idle handler will finish
119  // idle round.
120  static const int kMaxMarkCompactsInIdleRound;
121
122  // Number of scavenges that will trigger start of new idle round.
123  static const int kIdleScavengeThreshold;
124
125  // That is the maximum idle time we will have during frame rendering.
126  static const size_t kMaxFrameRenderingIdleTime = 16;
127
128  // If we haven't recorded any scavenger events yet, we use a conservative
129  // lower bound for the scavenger speed.
130  static const size_t kInitialConservativeScavengeSpeed = 100 * KB;
131
132  // If contexts are disposed at a higher rate a full gc is triggered.
133  static const double kHighContextDisposalRate;
134
135  // Incremental marking step time.
136  static const size_t kIncrementalMarkingStepTimeInMs = 1;
137
138  class HeapState {
139   public:
140    void Print();
141
142    int contexts_disposed;
143    double contexts_disposal_rate;
144    size_t size_of_objects;
145    bool incremental_marking_stopped;
146    bool can_start_incremental_marking;
147    bool sweeping_in_progress;
148    size_t mark_compact_speed_in_bytes_per_ms;
149    size_t incremental_marking_speed_in_bytes_per_ms;
150    size_t final_incremental_mark_compact_speed_in_bytes_per_ms;
151    size_t scavenge_speed_in_bytes_per_ms;
152    size_t used_new_space_size;
153    size_t new_space_capacity;
154    size_t new_space_allocation_throughput_in_bytes_per_ms;
155  };
156
157  GCIdleTimeHandler()
158      : mark_compacts_since_idle_round_started_(0),
159        scavenges_since_last_idle_round_(0) {}
160
161  GCIdleTimeAction Compute(double idle_time_in_ms, HeapState heap_state);
162
163  void NotifyIdleMarkCompact() {
164    if (mark_compacts_since_idle_round_started_ < kMaxMarkCompactsInIdleRound) {
165      ++mark_compacts_since_idle_round_started_;
166      if (mark_compacts_since_idle_round_started_ ==
167          kMaxMarkCompactsInIdleRound) {
168        scavenges_since_last_idle_round_ = 0;
169      }
170    }
171  }
172
173  void NotifyScavenge() { ++scavenges_since_last_idle_round_; }
174
175  static size_t EstimateMarkingStepSize(size_t idle_time_in_ms,
176                                        size_t marking_speed_in_bytes_per_ms);
177
178  static size_t EstimateMarkCompactTime(
179      size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);
180
181  static size_t EstimateFinalIncrementalMarkCompactTime(
182      size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);
183
184  static bool ShouldDoMarkCompact(size_t idle_time_in_ms,
185                                  size_t size_of_objects,
186                                  size_t mark_compact_speed_in_bytes_per_ms);
187
188  static bool ShouldDoContextDisposalMarkCompact(int context_disposed,
189                                                 double contexts_disposal_rate);
190
191  static bool ShouldDoFinalIncrementalMarkCompact(
192      size_t idle_time_in_ms, size_t size_of_objects,
193      size_t final_incremental_mark_compact_speed_in_bytes_per_ms);
194
195  static bool ShouldDoScavenge(
196      size_t idle_time_in_ms, size_t new_space_size, size_t used_new_space_size,
197      size_t scavenger_speed_in_bytes_per_ms,
198      size_t new_space_allocation_throughput_in_bytes_per_ms);
199
200 private:
201  void StartIdleRound() { mark_compacts_since_idle_round_started_ = 0; }
202  bool IsMarkCompactIdleRoundFinished() {
203    return mark_compacts_since_idle_round_started_ ==
204           kMaxMarkCompactsInIdleRound;
205  }
206  bool EnoughGarbageSinceLastIdleRound() {
207    return scavenges_since_last_idle_round_ >= kIdleScavengeThreshold;
208  }
209
210  int mark_compacts_since_idle_round_started_;
211  int scavenges_since_last_idle_round_;
212
213  DISALLOW_COPY_AND_ASSIGN(GCIdleTimeHandler);
214};
215
216}  // namespace internal
217}  // namespace v8
218
219#endif  // V8_HEAP_GC_IDLE_TIME_HANDLER_H_
220