6e7b710c6ad2dbfbc73b340d734df1e09cac61d8
[platform/upstream/nodejs.git] / deps / v8 / src / heap / gc-idle-time-handler.h
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
10 namespace v8 {
11 namespace internal {
12
13 enum GCIdleTimeActionType {
14   DONE,
15   DO_NOTHING,
16   DO_INCREMENTAL_MARKING,
17   DO_SCAVENGE,
18   DO_FULL_GC,
19   DO_FINALIZE_SWEEPING
20 };
21
22
23 class 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
81 class GCTracer;
82
83 // The idle time handler makes decisions about which garbage collection
84 // operations are executing during IdleNotification.
85 class 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   // Minimum idle time to start incremental marking.
129   static const size_t kMinIdleTimeToStartIncrementalMarking = 10;
130
131   // If we haven't recorded any scavenger events yet, we use a conservative
132   // lower bound for the scavenger speed.
133   static const size_t kInitialConservativeScavengeSpeed = 100 * KB;
134
135   // If contexts are disposed at a higher rate a full gc is triggered.
136   static const double kHighContextDisposalRate;
137
138   // Incremental marking step time.
139   static const size_t kIncrementalMarkingStepTimeInMs = 1;
140
141   class HeapState {
142    public:
143     void Print();
144
145     int contexts_disposed;
146     double contexts_disposal_rate;
147     size_t size_of_objects;
148     bool incremental_marking_stopped;
149     bool can_start_incremental_marking;
150     bool sweeping_in_progress;
151     size_t mark_compact_speed_in_bytes_per_ms;
152     size_t incremental_marking_speed_in_bytes_per_ms;
153     size_t final_incremental_mark_compact_speed_in_bytes_per_ms;
154     size_t scavenge_speed_in_bytes_per_ms;
155     size_t used_new_space_size;
156     size_t new_space_capacity;
157     size_t new_space_allocation_throughput_in_bytes_per_ms;
158   };
159
160   GCIdleTimeHandler()
161       : mark_compacts_since_idle_round_started_(0),
162         scavenges_since_last_idle_round_(0) {}
163
164   GCIdleTimeAction Compute(double idle_time_in_ms, HeapState heap_state);
165
166   void NotifyIdleMarkCompact() {
167     if (mark_compacts_since_idle_round_started_ < kMaxMarkCompactsInIdleRound) {
168       ++mark_compacts_since_idle_round_started_;
169       if (mark_compacts_since_idle_round_started_ ==
170           kMaxMarkCompactsInIdleRound) {
171         scavenges_since_last_idle_round_ = 0;
172       }
173     }
174   }
175
176   void NotifyScavenge() { ++scavenges_since_last_idle_round_; }
177
178   static size_t EstimateMarkingStepSize(size_t idle_time_in_ms,
179                                         size_t marking_speed_in_bytes_per_ms);
180
181   static size_t EstimateMarkCompactTime(
182       size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);
183
184   static size_t EstimateFinalIncrementalMarkCompactTime(
185       size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);
186
187   static bool ShouldDoMarkCompact(size_t idle_time_in_ms,
188                                   size_t size_of_objects,
189                                   size_t mark_compact_speed_in_bytes_per_ms);
190
191   static bool ShouldDoContextDisposalMarkCompact(int context_disposed,
192                                                  double contexts_disposal_rate);
193
194   static bool ShouldDoFinalIncrementalMarkCompact(
195       size_t idle_time_in_ms, size_t size_of_objects,
196       size_t final_incremental_mark_compact_speed_in_bytes_per_ms);
197
198   static bool ShouldDoScavenge(
199       size_t idle_time_in_ms, size_t new_space_size, size_t used_new_space_size,
200       size_t scavenger_speed_in_bytes_per_ms,
201       size_t new_space_allocation_throughput_in_bytes_per_ms);
202
203  private:
204   void StartIdleRound() { mark_compacts_since_idle_round_started_ = 0; }
205   bool IsMarkCompactIdleRoundFinished() {
206     return mark_compacts_since_idle_round_started_ ==
207            kMaxMarkCompactsInIdleRound;
208   }
209   bool EnoughGarbageSinceLastIdleRound() {
210     return scavenges_since_last_idle_round_ >= kIdleScavengeThreshold;
211   }
212
213   int mark_compacts_since_idle_round_started_;
214   int scavenges_since_last_idle_round_;
215
216   DISALLOW_COPY_AND_ASSIGN(GCIdleTimeHandler);
217 };
218
219 }  // namespace internal
220 }  // namespace v8
221
222 #endif  // V8_HEAP_GC_IDLE_TIME_HANDLER_H_