OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <limits> | 5 #include <limits> |
6 | 6 |
7 #include "src/flags.h" | 7 #include "src/flags.h" |
8 #include "src/heap/memory-reducer.h" | 8 #include "src/heap/memory-reducer.h" |
9 #include "testing/gtest/include/gtest/gtest.h" | 9 #include "testing/gtest/include/gtest/gtest.h" |
10 | 10 |
11 namespace v8 { | 11 namespace v8 { |
12 namespace internal { | 12 namespace internal { |
13 | 13 |
14 MemoryReducer::State DoneState() { | 14 MemoryReducer::State DoneState() { |
15 return MemoryReducer::State(MemoryReducer::kDone, 0, 0.0, 1.0); | 15 return MemoryReducer::State(MemoryReducer::kDone, 0, 0.0, 1.0, 0); |
16 } | 16 } |
17 | 17 |
| 18 MemoryReducer::State DoneState(size_t committed_memory) { |
| 19 return MemoryReducer::State(MemoryReducer::kDone, 0, 0.0, 1.0, |
| 20 committed_memory); |
| 21 } |
18 | 22 |
19 MemoryReducer::State WaitState(int started_gcs, double next_gc_start_ms) { | 23 MemoryReducer::State WaitState(int started_gcs, double next_gc_start_ms) { |
20 return MemoryReducer::State(MemoryReducer::kWait, started_gcs, | 24 return MemoryReducer::State(MemoryReducer::kWait, started_gcs, |
21 next_gc_start_ms, 1.0); | 25 next_gc_start_ms, 1.0, 0); |
22 } | 26 } |
23 | 27 |
24 | 28 |
25 MemoryReducer::State RunState(int started_gcs, double next_gc_start_ms) { | 29 MemoryReducer::State RunState(int started_gcs, double next_gc_start_ms) { |
26 return MemoryReducer::State(MemoryReducer::kRun, started_gcs, | 30 return MemoryReducer::State(MemoryReducer::kRun, started_gcs, |
27 next_gc_start_ms, 1.0); | 31 next_gc_start_ms, 1.0, 0); |
28 } | 32 } |
29 | 33 |
30 MemoryReducer::Event MarkCompactEvent(double time_ms, | 34 MemoryReducer::Event MarkCompactEvent(double time_ms, |
31 bool next_gc_likely_to_collect_more) { | 35 bool next_gc_likely_to_collect_more, |
| 36 size_t committed_memory) { |
32 MemoryReducer::Event event; | 37 MemoryReducer::Event event; |
33 event.type = MemoryReducer::kMarkCompact; | 38 event.type = MemoryReducer::kMarkCompact; |
34 event.time_ms = time_ms; | 39 event.time_ms = time_ms; |
35 event.next_gc_likely_to_collect_more = next_gc_likely_to_collect_more; | 40 event.next_gc_likely_to_collect_more = next_gc_likely_to_collect_more; |
| 41 event.committed_memory = committed_memory; |
36 return event; | 42 return event; |
37 } | 43 } |
38 | 44 |
39 MemoryReducer::Event MarkCompactEventGarbageLeft(double time_ms) { | 45 MemoryReducer::Event MarkCompactEventGarbageLeft(double time_ms, |
40 return MarkCompactEvent(time_ms, true); | 46 size_t committed_memory) { |
| 47 return MarkCompactEvent(time_ms, true, committed_memory); |
41 } | 48 } |
42 | 49 |
43 MemoryReducer::Event MarkCompactEventNoGarbageLeft(double time_ms) { | 50 MemoryReducer::Event MarkCompactEventNoGarbageLeft(double time_ms, |
44 return MarkCompactEvent(time_ms, false); | 51 size_t committed_memory) { |
| 52 return MarkCompactEvent(time_ms, false, committed_memory); |
45 } | 53 } |
46 | 54 |
47 | 55 |
48 MemoryReducer::Event TimerEvent(double time_ms, | 56 MemoryReducer::Event TimerEvent(double time_ms, |
49 bool should_start_incremental_gc, | 57 bool should_start_incremental_gc, |
50 bool can_start_incremental_gc) { | 58 bool can_start_incremental_gc) { |
51 MemoryReducer::Event event; | 59 MemoryReducer::Event event; |
52 event.type = MemoryReducer::kTimer; | 60 event.type = MemoryReducer::kTimer; |
53 event.time_ms = time_ms; | 61 event.time_ms = time_ms; |
54 event.should_start_incremental_gc = should_start_incremental_gc; | 62 event.should_start_incremental_gc = should_start_incremental_gc; |
(...skipping 28 matching lines...) Expand all Loading... |
83 MemoryReducer::State state0(DoneState()), state1(DoneState()); | 91 MemoryReducer::State state0(DoneState()), state1(DoneState()); |
84 | 92 |
85 state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(0)); | 93 state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(0)); |
86 EXPECT_EQ(MemoryReducer::kDone, state1.action); | 94 EXPECT_EQ(MemoryReducer::kDone, state1.action); |
87 | 95 |
88 state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(0)); | 96 state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(0)); |
89 EXPECT_EQ(MemoryReducer::kDone, state1.action); | 97 EXPECT_EQ(MemoryReducer::kDone, state1.action); |
90 | 98 |
91 state1 = MemoryReducer::Step(state0, TimerEventPendingGC(0)); | 99 state1 = MemoryReducer::Step(state0, TimerEventPendingGC(0)); |
92 EXPECT_EQ(MemoryReducer::kDone, state1.action); | 100 EXPECT_EQ(MemoryReducer::kDone, state1.action); |
| 101 |
| 102 state1 = MemoryReducer::Step( |
| 103 state0, |
| 104 MarkCompactEventGarbageLeft(0, MemoryReducer::kCommittedMemoryDelta - 1)); |
| 105 EXPECT_EQ(MemoryReducer::kDone, state1.action); |
| 106 |
| 107 state0 = DoneState(1000 * MB); |
| 108 state1 = MemoryReducer::Step( |
| 109 state0, MarkCompactEventGarbageLeft( |
| 110 0, static_cast<size_t>( |
| 111 1000 * MB * MemoryReducer::kCommittedMemoryFactor) - |
| 112 1)); |
| 113 EXPECT_EQ(MemoryReducer::kDone, state1.action); |
93 } | 114 } |
94 | 115 |
95 | 116 |
96 TEST(MemoryReducer, FromDoneToWait) { | 117 TEST(MemoryReducer, FromDoneToWait) { |
97 if (!FLAG_incremental_marking) return; | 118 if (!FLAG_incremental_marking) return; |
98 | 119 |
99 MemoryReducer::State state0(DoneState()), state1(DoneState()); | 120 MemoryReducer::State state0(DoneState()), state1(DoneState()); |
100 | 121 |
101 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2)); | 122 state1 = MemoryReducer::Step( |
| 123 state0, |
| 124 MarkCompactEventGarbageLeft(2, MemoryReducer::kCommittedMemoryDelta)); |
102 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 125 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
103 EXPECT_EQ(MemoryReducer::kLongDelayMs + 2, state1.next_gc_start_ms); | 126 EXPECT_EQ(MemoryReducer::kLongDelayMs + 2, state1.next_gc_start_ms); |
104 EXPECT_EQ(0, state1.started_gcs); | 127 EXPECT_EQ(0, state1.started_gcs); |
105 EXPECT_EQ(2, state1.last_gc_time_ms); | 128 EXPECT_EQ(2, state1.last_gc_time_ms); |
106 | 129 |
107 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2)); | 130 state1 = MemoryReducer::Step( |
| 131 state0, |
| 132 MarkCompactEventNoGarbageLeft(2, MemoryReducer::kCommittedMemoryDelta)); |
108 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 133 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
109 EXPECT_EQ(MemoryReducer::kLongDelayMs + 2, state1.next_gc_start_ms); | 134 EXPECT_EQ(MemoryReducer::kLongDelayMs + 2, state1.next_gc_start_ms); |
110 EXPECT_EQ(0, state1.started_gcs); | 135 EXPECT_EQ(0, state1.started_gcs); |
111 EXPECT_EQ(2, state1.last_gc_time_ms); | 136 EXPECT_EQ(2, state1.last_gc_time_ms); |
112 | 137 |
113 state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(0)); | 138 state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(0)); |
114 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 139 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
115 EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | 140 EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); |
116 EXPECT_EQ(0, state1.started_gcs); | 141 EXPECT_EQ(0, state1.started_gcs); |
117 EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); | 142 EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); |
| 143 |
| 144 state0 = DoneState(1000 * MB); |
| 145 state1 = MemoryReducer::Step( |
| 146 state0, MarkCompactEventGarbageLeft( |
| 147 2, static_cast<size_t>( |
| 148 1000 * MB * MemoryReducer::kCommittedMemoryFactor))); |
| 149 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
| 150 EXPECT_EQ(MemoryReducer::kLongDelayMs + 2, state1.next_gc_start_ms); |
| 151 EXPECT_EQ(0, state1.started_gcs); |
| 152 EXPECT_EQ(2, state1.last_gc_time_ms); |
118 } | 153 } |
119 | 154 |
120 | 155 |
121 TEST(MemoryReducer, FromWaitToWait) { | 156 TEST(MemoryReducer, FromWaitToWait) { |
122 if (!FLAG_incremental_marking) return; | 157 if (!FLAG_incremental_marking) return; |
123 | 158 |
124 MemoryReducer::State state0(WaitState(2, 1000.0)), state1(DoneState()); | 159 MemoryReducer::State state0(WaitState(2, 1000.0)), state1(DoneState()); |
125 | 160 |
126 state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(2000)); | 161 state1 = MemoryReducer::Step(state0, PossibleGarbageEvent(2000)); |
127 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 162 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
128 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); | 163 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
129 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | 164 EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
130 | 165 |
131 state1 = MemoryReducer::Step( | 166 state1 = MemoryReducer::Step( |
132 state0, TimerEventLowAllocationRate(state0.next_gc_start_ms - 1)); | 167 state0, TimerEventLowAllocationRate(state0.next_gc_start_ms - 1)); |
133 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 168 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
134 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); | 169 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); |
135 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | 170 EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
136 | 171 |
137 state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000)); | 172 state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000)); |
138 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 173 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
139 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | 174 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); |
140 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | 175 EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
141 | 176 |
142 state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000)); | 177 state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000)); |
143 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 178 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
144 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | 179 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); |
145 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | 180 EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
146 | 181 |
147 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000)); | 182 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000, 0)); |
148 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 183 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
149 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | 184 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); |
150 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | 185 EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
151 EXPECT_EQ(2000, state1.last_gc_time_ms); | 186 EXPECT_EQ(2000, state1.last_gc_time_ms); |
152 | 187 |
153 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000)); | 188 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000, 0)); |
154 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 189 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
155 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | 190 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); |
156 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | 191 EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
157 EXPECT_EQ(2000, state1.last_gc_time_ms); | 192 EXPECT_EQ(2000, state1.last_gc_time_ms); |
158 | 193 |
159 state0.last_gc_time_ms = 0; | 194 state0.last_gc_time_ms = 0; |
160 state1 = MemoryReducer::Step( | 195 state1 = MemoryReducer::Step( |
161 state0, | 196 state0, |
162 TimerEventHighAllocationRate(MemoryReducer::kWatchdogDelayMs + 1)); | 197 TimerEventHighAllocationRate(MemoryReducer::kWatchdogDelayMs + 1)); |
163 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 198 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | 287 EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
253 EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); | 288 EXPECT_EQ(state0.last_gc_time_ms, state1.last_gc_time_ms); |
254 } | 289 } |
255 | 290 |
256 | 291 |
257 TEST(MemoryReducer, FromRunToDone) { | 292 TEST(MemoryReducer, FromRunToDone) { |
258 if (!FLAG_incremental_marking) return; | 293 if (!FLAG_incremental_marking) return; |
259 | 294 |
260 MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState()); | 295 MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState()); |
261 | 296 |
262 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000)); | 297 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000, 0)); |
263 EXPECT_EQ(MemoryReducer::kDone, state1.action); | 298 EXPECT_EQ(MemoryReducer::kDone, state1.action); |
264 EXPECT_EQ(0, state1.next_gc_start_ms); | 299 EXPECT_EQ(0, state1.next_gc_start_ms); |
265 EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs); | 300 EXPECT_EQ(MemoryReducer::kMaxNumberOfGCs, state1.started_gcs); |
266 EXPECT_EQ(2000, state1.last_gc_time_ms); | 301 EXPECT_EQ(2000, state1.last_gc_time_ms); |
267 | 302 |
268 state0.started_gcs = MemoryReducer::kMaxNumberOfGCs; | 303 state0.started_gcs = MemoryReducer::kMaxNumberOfGCs; |
269 | 304 |
270 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000)); | 305 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000, 0)); |
271 EXPECT_EQ(MemoryReducer::kDone, state1.action); | 306 EXPECT_EQ(MemoryReducer::kDone, state1.action); |
272 EXPECT_EQ(0, state1.next_gc_start_ms); | 307 EXPECT_EQ(0, state1.next_gc_start_ms); |
273 EXPECT_EQ(2000, state1.last_gc_time_ms); | 308 EXPECT_EQ(2000, state1.last_gc_time_ms); |
274 } | 309 } |
275 | 310 |
276 | 311 |
277 TEST(MemoryReducer, FromRunToWait) { | 312 TEST(MemoryReducer, FromRunToWait) { |
278 if (!FLAG_incremental_marking) return; | 313 if (!FLAG_incremental_marking) return; |
279 | 314 |
280 MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState()); | 315 MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState()); |
281 | 316 |
282 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000)); | 317 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000, 0)); |
283 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 318 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
284 EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms); | 319 EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms); |
285 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | 320 EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
286 EXPECT_EQ(2000, state1.last_gc_time_ms); | 321 EXPECT_EQ(2000, state1.last_gc_time_ms); |
287 | 322 |
288 state0.started_gcs = 1; | 323 state0.started_gcs = 1; |
289 | 324 |
290 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000)); | 325 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000, 0)); |
291 EXPECT_EQ(MemoryReducer::kWait, state1.action); | 326 EXPECT_EQ(MemoryReducer::kWait, state1.action); |
292 EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms); | 327 EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms); |
293 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | 328 EXPECT_EQ(state0.started_gcs, state1.started_gcs); |
294 EXPECT_EQ(2000, state1.last_gc_time_ms); | 329 EXPECT_EQ(2000, state1.last_gc_time_ms); |
295 } | 330 } |
296 | 331 |
297 } // namespace internal | 332 } // namespace internal |
298 } // namespace v8 | 333 } // namespace v8 |
OLD | NEW |