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 <limits>
6 :
7 : #include "src/heap/gc-idle-time-handler.h"
8 : #include "testing/gtest/include/gtest/gtest.h"
9 :
10 : namespace v8 {
11 : namespace internal {
12 :
13 : namespace {
14 :
15 : class GCIdleTimeHandlerTest : public ::testing::Test {
16 : public:
17 13 : GCIdleTimeHandlerTest() = default;
18 13 : ~GCIdleTimeHandlerTest() override = default;
19 :
20 11 : GCIdleTimeHandler* handler() { return &handler_; }
21 :
22 : GCIdleTimeHeapState DefaultHeapState() {
23 : GCIdleTimeHeapState result;
24 11 : result.contexts_disposed = 0;
25 11 : result.contexts_disposal_rate = GCIdleTimeHandler::kHighContextDisposalRate;
26 11 : result.incremental_marking_stopped = false;
27 11 : result.size_of_objects = kSizeOfObjects;
28 : return result;
29 : }
30 :
31 : static const size_t kSizeOfObjects = 100 * MB;
32 : static const size_t kMarkCompactSpeed = 200 * KB;
33 : static const size_t kMarkingSpeed = 200 * KB;
34 :
35 : private:
36 : GCIdleTimeHandler handler_;
37 : };
38 :
39 : } // namespace
40 :
41 :
42 15443 : TEST(GCIdleTimeHandler, EstimateMarkingStepSizeInitial) {
43 1 : size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(1, 0);
44 2 : EXPECT_EQ(
45 : static_cast<size_t>(GCIdleTimeHandler::kInitialConservativeMarkingSpeed *
46 : GCIdleTimeHandler::kConservativeTimeRatio),
47 0 : step_size);
48 1 : }
49 :
50 :
51 15443 : TEST(GCIdleTimeHandler, EstimateMarkingStepSizeNonZero) {
52 : size_t marking_speed_in_bytes_per_millisecond = 100;
53 1 : size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
54 1 : 1, marking_speed_in_bytes_per_millisecond);
55 2 : EXPECT_EQ(static_cast<size_t>(marking_speed_in_bytes_per_millisecond *
56 : GCIdleTimeHandler::kConservativeTimeRatio),
57 0 : step_size);
58 1 : }
59 :
60 :
61 15443 : TEST(GCIdleTimeHandler, EstimateMarkingStepSizeOverflow1) {
62 1 : size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
63 1 : 10, std::numeric_limits<size_t>::max());
64 2 : EXPECT_EQ(static_cast<size_t>(GCIdleTimeHandler::kMaximumMarkingStepSize),
65 0 : step_size);
66 1 : }
67 :
68 :
69 15443 : TEST(GCIdleTimeHandler, EstimateMarkingStepSizeOverflow2) {
70 1 : size_t step_size = GCIdleTimeHandler::EstimateMarkingStepSize(
71 1 : std::numeric_limits<size_t>::max(), 10);
72 2 : EXPECT_EQ(static_cast<size_t>(GCIdleTimeHandler::kMaximumMarkingStepSize),
73 0 : step_size);
74 1 : }
75 :
76 :
77 15444 : TEST_F(GCIdleTimeHandlerTest, ShouldDoFinalIncrementalMarkCompact) {
78 : size_t idle_time_ms = 16;
79 2 : EXPECT_TRUE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
80 0 : idle_time_ms, 0, 0));
81 1 : }
82 :
83 :
84 15444 : TEST_F(GCIdleTimeHandlerTest, DontDoFinalIncrementalMarkCompact) {
85 : size_t idle_time_ms = 1;
86 2 : EXPECT_FALSE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact(
87 0 : idle_time_ms, kSizeOfObjects, kMarkingSpeed));
88 1 : }
89 :
90 :
91 15444 : TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) {
92 1 : if (!handler()->Enabled()) return;
93 : GCIdleTimeHeapState heap_state = DefaultHeapState();
94 1 : heap_state.contexts_disposed = 1;
95 1 : heap_state.incremental_marking_stopped = true;
96 : double idle_time_ms = 0;
97 2 : EXPECT_EQ(GCIdleTimeAction::kDone,
98 0 : handler()->Compute(idle_time_ms, heap_state));
99 : }
100 :
101 :
102 15444 : TEST_F(GCIdleTimeHandlerTest, ContextDisposeHighRate) {
103 1 : if (!handler()->Enabled()) return;
104 : GCIdleTimeHeapState heap_state = DefaultHeapState();
105 1 : heap_state.contexts_disposed = 1;
106 : heap_state.contexts_disposal_rate =
107 1 : GCIdleTimeHandler::kHighContextDisposalRate - 1;
108 1 : heap_state.incremental_marking_stopped = true;
109 : double idle_time_ms = 0;
110 2 : EXPECT_EQ(GCIdleTimeAction::kFullGC,
111 0 : handler()->Compute(idle_time_ms, heap_state));
112 : }
113 :
114 :
115 15444 : TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeZeroIdleTime) {
116 1 : if (!handler()->Enabled()) return;
117 : GCIdleTimeHeapState heap_state = DefaultHeapState();
118 1 : heap_state.contexts_disposed = 1;
119 1 : heap_state.contexts_disposal_rate = 1.0;
120 1 : heap_state.incremental_marking_stopped = true;
121 : double idle_time_ms = 0;
122 2 : EXPECT_EQ(GCIdleTimeAction::kFullGC,
123 0 : handler()->Compute(idle_time_ms, heap_state));
124 : }
125 :
126 :
127 15444 : TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime1) {
128 1 : if (!handler()->Enabled()) return;
129 : GCIdleTimeHeapState heap_state = DefaultHeapState();
130 1 : heap_state.contexts_disposed = 1;
131 : heap_state.contexts_disposal_rate =
132 : GCIdleTimeHandler::kHighContextDisposalRate;
133 : size_t speed = kMarkCompactSpeed;
134 : double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
135 2 : EXPECT_EQ(GCIdleTimeAction::kIncrementalStep,
136 0 : handler()->Compute(idle_time_ms, heap_state));
137 : }
138 :
139 :
140 15444 : TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeSmallIdleTime2) {
141 1 : if (!handler()->Enabled()) return;
142 : GCIdleTimeHeapState heap_state = DefaultHeapState();
143 1 : heap_state.contexts_disposed = 1;
144 : heap_state.contexts_disposal_rate =
145 : GCIdleTimeHandler::kHighContextDisposalRate;
146 : size_t speed = kMarkCompactSpeed;
147 : double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
148 2 : EXPECT_EQ(GCIdleTimeAction::kIncrementalStep,
149 0 : handler()->Compute(idle_time_ms, heap_state));
150 : }
151 :
152 15444 : TEST_F(GCIdleTimeHandlerTest, AfterContextDisposeLargeHeap) {
153 1 : if (!handler()->Enabled()) return;
154 : GCIdleTimeHeapState heap_state = DefaultHeapState();
155 1 : heap_state.contexts_disposed = 1;
156 1 : heap_state.contexts_disposal_rate = 1.0;
157 1 : heap_state.incremental_marking_stopped = true;
158 1 : heap_state.size_of_objects = 101 * MB;
159 : double idle_time_ms = 0;
160 2 : EXPECT_EQ(GCIdleTimeAction::kDone,
161 0 : handler()->Compute(idle_time_ms, heap_state));
162 : }
163 :
164 15444 : TEST_F(GCIdleTimeHandlerTest, IncrementalMarking1) {
165 1 : if (!handler()->Enabled()) return;
166 : GCIdleTimeHeapState heap_state = DefaultHeapState();
167 : double idle_time_ms = 10;
168 2 : EXPECT_EQ(GCIdleTimeAction::kIncrementalStep,
169 0 : handler()->Compute(idle_time_ms, heap_state));
170 : }
171 :
172 :
173 15444 : TEST_F(GCIdleTimeHandlerTest, NotEnoughTime) {
174 1 : if (!handler()->Enabled()) return;
175 : GCIdleTimeHeapState heap_state = DefaultHeapState();
176 1 : heap_state.incremental_marking_stopped = true;
177 : size_t speed = kMarkCompactSpeed;
178 : double idle_time_ms = static_cast<double>(kSizeOfObjects / speed - 1);
179 2 : EXPECT_EQ(GCIdleTimeAction::kDone,
180 0 : handler()->Compute(idle_time_ms, heap_state));
181 : }
182 :
183 :
184 15444 : TEST_F(GCIdleTimeHandlerTest, DoNotStartIncrementalMarking) {
185 1 : if (!handler()->Enabled()) return;
186 : GCIdleTimeHeapState heap_state = DefaultHeapState();
187 1 : heap_state.incremental_marking_stopped = true;
188 : double idle_time_ms = 10.0;
189 2 : EXPECT_EQ(GCIdleTimeAction::kDone,
190 0 : handler()->Compute(idle_time_ms, heap_state));
191 : }
192 :
193 :
194 15444 : TEST_F(GCIdleTimeHandlerTest, ContinueAfterStop) {
195 1 : if (!handler()->Enabled()) return;
196 : GCIdleTimeHeapState heap_state = DefaultHeapState();
197 1 : heap_state.incremental_marking_stopped = true;
198 : double idle_time_ms = 10.0;
199 2 : EXPECT_EQ(GCIdleTimeAction::kDone,
200 0 : handler()->Compute(idle_time_ms, heap_state));
201 1 : heap_state.incremental_marking_stopped = false;
202 2 : EXPECT_EQ(GCIdleTimeAction::kIncrementalStep,
203 0 : handler()->Compute(idle_time_ms, heap_state));
204 : }
205 :
206 :
207 15444 : TEST_F(GCIdleTimeHandlerTest, DoneIfNotMakingProgressOnIncrementalMarking) {
208 1 : if (!handler()->Enabled()) return;
209 :
210 : // Regression test for crbug.com/489323.
211 : GCIdleTimeHeapState heap_state = DefaultHeapState();
212 :
213 : // Simulate incremental marking stopped and not eligible to start.
214 1 : heap_state.incremental_marking_stopped = true;
215 : double idle_time_ms = 10.0;
216 : // We should return kDone if we cannot start incremental marking.
217 2 : EXPECT_EQ(GCIdleTimeAction::kDone,
218 0 : handler()->Compute(idle_time_ms, heap_state));
219 : }
220 :
221 : } // namespace internal
222 9264 : } // namespace v8
|