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    return result;
30  }
31
32  static GCIdleTimeAction Nothing() {
33    GCIdleTimeAction result;
34    result.type = DO_NOTHING;
35    result.parameter = 0;
36    return result;
37  }
38
39  static GCIdleTimeAction IncrementalMarking(intptr_t step_size) {
40    GCIdleTimeAction result;
41    result.type = DO_INCREMENTAL_MARKING;
42    result.parameter = step_size;
43    return result;
44  }
45
46  static GCIdleTimeAction Scavenge() {
47    GCIdleTimeAction result;
48    result.type = DO_SCAVENGE;
49    result.parameter = 0;
50    return result;
51  }
52
53  static GCIdleTimeAction FullGC() {
54    GCIdleTimeAction result;
55    result.type = DO_FULL_GC;
56    result.parameter = 0;
57    return result;
58  }
59
60  static GCIdleTimeAction FinalizeSweeping() {
61    GCIdleTimeAction result;
62    result.type = DO_FINALIZE_SWEEPING;
63    result.parameter = 0;
64    return result;
65  }
66
67  void Print();
68
69  GCIdleTimeActionType type;
70  intptr_t parameter;
71};
72
73
74class GCTracer;
75
76// The idle time handler makes decisions about which garbage collection
77// operations are executing during IdleNotification.
78class GCIdleTimeHandler {
79 public:
80  // If we haven't recorded any incremental marking events yet, we carefully
81  // mark with a conservative lower bound for the marking speed.
82  static const size_t kInitialConservativeMarkingSpeed = 100 * KB;
83
84  // Maximum marking step size returned by EstimateMarkingStepSize.
85  static const size_t kMaximumMarkingStepSize = 700 * MB;
86
87  // We have to make sure that we finish the IdleNotification before
88  // idle_time_in_ms. Hence, we conservatively prune our workload estimate.
89  static const double kConservativeTimeRatio;
90
91  // If we haven't recorded any mark-compact events yet, we use
92  // conservative lower bound for the mark-compact speed.
93  static const size_t kInitialConservativeMarkCompactSpeed = 2 * MB;
94
95  // Maximum mark-compact time returned by EstimateMarkCompactTime.
96  static const size_t kMaxMarkCompactTimeInMs;
97
98  // Minimum time to finalize sweeping phase. The main thread may wait for
99  // sweeper threads.
100  static const size_t kMinTimeForFinalizeSweeping;
101
102  // Number of idle mark-compact events, after which idle handler will finish
103  // idle round.
104  static const int kMaxMarkCompactsInIdleRound;
105
106  // Number of scavenges that will trigger start of new idle round.
107  static const int kIdleScavengeThreshold;
108
109  // Heap size threshold below which we prefer mark-compact over incremental
110  // step.
111  static const size_t kSmallHeapSize = 4 * kPointerSize * MB;
112
113  // That is the maximum idle time we will have during frame rendering.
114  static const size_t kMaxFrameRenderingIdleTime = 16;
115
116  // If less than that much memory is left in the new space, we consider it
117  // as almost full and force a new space collection earlier in the idle time.
118  static const size_t kNewSpaceAlmostFullTreshold = 100 * KB;
119
120  // If we haven't recorded any scavenger events yet, we use a conservative
121  // lower bound for the scavenger speed.
122  static const size_t kInitialConservativeScavengeSpeed = 100 * KB;
123
124  struct HeapState {
125    int contexts_disposed;
126    size_t size_of_objects;
127    bool incremental_marking_stopped;
128    bool can_start_incremental_marking;
129    bool sweeping_in_progress;
130    size_t mark_compact_speed_in_bytes_per_ms;
131    size_t incremental_marking_speed_in_bytes_per_ms;
132    size_t scavenge_speed_in_bytes_per_ms;
133    size_t available_new_space_memory;
134    size_t new_space_capacity;
135    size_t new_space_allocation_throughput_in_bytes_per_ms;
136  };
137
138  GCIdleTimeHandler()
139      : mark_compacts_since_idle_round_started_(0),
140        scavenges_since_last_idle_round_(0) {}
141
142  GCIdleTimeAction Compute(size_t idle_time_in_ms, HeapState heap_state);
143
144  void NotifyIdleMarkCompact() {
145    if (mark_compacts_since_idle_round_started_ < kMaxMarkCompactsInIdleRound) {
146      ++mark_compacts_since_idle_round_started_;
147      if (mark_compacts_since_idle_round_started_ ==
148          kMaxMarkCompactsInIdleRound) {
149        scavenges_since_last_idle_round_ = 0;
150      }
151    }
152  }
153
154  void NotifyScavenge() { ++scavenges_since_last_idle_round_; }
155
156  static size_t EstimateMarkingStepSize(size_t idle_time_in_ms,
157                                        size_t marking_speed_in_bytes_per_ms);
158
159  static size_t EstimateMarkCompactTime(
160      size_t size_of_objects, size_t mark_compact_speed_in_bytes_per_ms);
161
162  static size_t EstimateScavengeTime(size_t new_space_size,
163                                     size_t scavenger_speed_in_bytes_per_ms);
164
165  static bool ScavangeMayHappenSoon(
166      size_t available_new_space_memory,
167      size_t new_space_allocation_throughput_in_bytes_per_ms);
168
169 private:
170  void StartIdleRound() { mark_compacts_since_idle_round_started_ = 0; }
171  bool IsMarkCompactIdleRoundFinished() {
172    return mark_compacts_since_idle_round_started_ ==
173           kMaxMarkCompactsInIdleRound;
174  }
175  bool EnoughGarbageSinceLastIdleRound() {
176    return scavenges_since_last_idle_round_ >= kIdleScavengeThreshold;
177  }
178
179  int mark_compacts_since_idle_round_started_;
180  int scavenges_since_last_idle_round_;
181
182  DISALLOW_COPY_AND_ASSIGN(GCIdleTimeHandler);
183};
184
185}  // namespace internal
186}  // namespace v8
187
188#endif  // V8_HEAP_GC_IDLE_TIME_HANDLER_H_
189