OLD | NEW |
| (Empty) |
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/flags.h" | |
8 #include "src/heap/memory-reducer.h" | |
9 #include "testing/gtest/include/gtest/gtest.h" | |
10 | |
11 namespace v8 { | |
12 namespace internal { | |
13 | |
14 MemoryReducer::State DoneState() { | |
15 return MemoryReducer::State(MemoryReducer::kDone, 0, 0.0); | |
16 } | |
17 | |
18 | |
19 MemoryReducer::State WaitState(int started_gcs, double next_gc_start_ms) { | |
20 return MemoryReducer::State(MemoryReducer::kWait, started_gcs, | |
21 next_gc_start_ms); | |
22 } | |
23 | |
24 | |
25 MemoryReducer::State RunState(int started_gcs, double next_gc_start_ms) { | |
26 return MemoryReducer::State(MemoryReducer::kRun, started_gcs, | |
27 next_gc_start_ms); | |
28 } | |
29 | |
30 | |
31 MemoryReducer::Event MarkCompactEvent(double time_ms, | |
32 bool next_gc_likely_to_collect_more) { | |
33 MemoryReducer::Event event; | |
34 event.type = MemoryReducer::kMarkCompact; | |
35 event.time_ms = time_ms; | |
36 event.next_gc_likely_to_collect_more = next_gc_likely_to_collect_more; | |
37 return event; | |
38 } | |
39 | |
40 | |
41 MemoryReducer::Event MarkCompactEventGarbageLeft(double time_ms) { | |
42 return MarkCompactEvent(time_ms, true); | |
43 } | |
44 | |
45 | |
46 MemoryReducer::Event MarkCompactEventNoGarbageLeft(double time_ms) { | |
47 return MarkCompactEvent(time_ms, false); | |
48 } | |
49 | |
50 | |
51 MemoryReducer::Event TimerEvent(double time_ms, bool low_allocation_rate, | |
52 bool can_start_incremental_gc) { | |
53 MemoryReducer::Event event; | |
54 event.type = MemoryReducer::kTimer; | |
55 event.time_ms = time_ms; | |
56 event.low_allocation_rate = low_allocation_rate; | |
57 event.can_start_incremental_gc = can_start_incremental_gc; | |
58 return event; | |
59 } | |
60 | |
61 | |
62 MemoryReducer::Event TimerEventLowAllocationRate(double time_ms) { | |
63 return TimerEvent(time_ms, true, true); | |
64 } | |
65 | |
66 | |
67 MemoryReducer::Event TimerEventHighAllocationRate(double time_ms) { | |
68 return TimerEvent(time_ms, false, true); | |
69 } | |
70 | |
71 | |
72 MemoryReducer::Event TimerEventPendingGC(double time_ms) { | |
73 return TimerEvent(time_ms, true, false); | |
74 } | |
75 | |
76 | |
77 MemoryReducer::Event ContextDisposedEvent(double time_ms) { | |
78 MemoryReducer::Event event; | |
79 event.type = MemoryReducer::kContextDisposed; | |
80 event.time_ms = time_ms; | |
81 return event; | |
82 } | |
83 | |
84 | |
85 TEST(MemoryReducer, FromDoneToDone) { | |
86 MemoryReducer::State state0(DoneState()), state1(DoneState()); | |
87 | |
88 state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(0)); | |
89 EXPECT_EQ(MemoryReducer::kDone, state1.action); | |
90 | |
91 state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(0)); | |
92 EXPECT_EQ(MemoryReducer::kDone, state1.action); | |
93 | |
94 state1 = MemoryReducer::Step(state0, TimerEventPendingGC(0)); | |
95 EXPECT_EQ(MemoryReducer::kDone, state1.action); | |
96 } | |
97 | |
98 | |
99 TEST(MemoryReducer, FromDoneToWait) { | |
100 if (!FLAG_incremental_marking) return; | |
101 | |
102 MemoryReducer::State state0(DoneState()), state1(DoneState()); | |
103 | |
104 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(0)); | |
105 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
106 EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | |
107 EXPECT_EQ(0, state1.started_gcs); | |
108 | |
109 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(0)); | |
110 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
111 EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | |
112 EXPECT_EQ(0, state1.started_gcs); | |
113 | |
114 state1 = MemoryReducer::Step(state0, ContextDisposedEvent(0)); | |
115 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
116 EXPECT_EQ(MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | |
117 EXPECT_EQ(0, state1.started_gcs); | |
118 } | |
119 | |
120 | |
121 TEST(MemoryReducer, FromWaitToWait) { | |
122 if (!FLAG_incremental_marking) return; | |
123 | |
124 MemoryReducer::State state0(WaitState(2, 1000.0)), state1(DoneState()); | |
125 | |
126 state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000)); | |
127 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
128 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); | |
129 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
130 | |
131 state1 = MemoryReducer::Step( | |
132 state0, TimerEventLowAllocationRate(state0.next_gc_start_ms - 1)); | |
133 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
134 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); | |
135 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
136 | |
137 state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000)); | |
138 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
139 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | |
140 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
141 | |
142 state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000)); | |
143 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
144 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | |
145 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
146 | |
147 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000)); | |
148 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
149 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | |
150 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
151 | |
152 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000)); | |
153 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
154 EXPECT_EQ(2000 + MemoryReducer::kLongDelayMs, state1.next_gc_start_ms); | |
155 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
156 } | |
157 | |
158 | |
159 TEST(MemoryReducer, FromWaitToRun) { | |
160 if (!FLAG_incremental_marking) return; | |
161 | |
162 MemoryReducer::State state0(WaitState(0, 1000.0)), state1(DoneState()); | |
163 | |
164 state1 = MemoryReducer::Step( | |
165 state0, TimerEventLowAllocationRate(state0.next_gc_start_ms + 1)); | |
166 EXPECT_EQ(MemoryReducer::kRun, state1.action); | |
167 EXPECT_EQ(0, state1.next_gc_start_ms); | |
168 EXPECT_EQ(state0.started_gcs + 1, state1.started_gcs); | |
169 } | |
170 | |
171 | |
172 TEST(MemoryReducer, FromRunToRun) { | |
173 if (!FLAG_incremental_marking) return; | |
174 | |
175 MemoryReducer::State state0(RunState(1, 0.0)), state1(DoneState()); | |
176 | |
177 state1 = MemoryReducer::Step(state0, TimerEventLowAllocationRate(2000)); | |
178 EXPECT_EQ(MemoryReducer::kRun, state1.action); | |
179 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); | |
180 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
181 | |
182 state1 = MemoryReducer::Step(state0, TimerEventHighAllocationRate(2000)); | |
183 EXPECT_EQ(MemoryReducer::kRun, state1.action); | |
184 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); | |
185 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
186 | |
187 state1 = MemoryReducer::Step(state0, TimerEventPendingGC(2000)); | |
188 EXPECT_EQ(MemoryReducer::kRun, state1.action); | |
189 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); | |
190 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
191 | |
192 state1 = MemoryReducer::Step(state0, ContextDisposedEvent(2000)); | |
193 EXPECT_EQ(MemoryReducer::kRun, state1.action); | |
194 EXPECT_EQ(state0.next_gc_start_ms, state1.next_gc_start_ms); | |
195 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
196 } | |
197 | |
198 | |
199 TEST(MemoryReducer, FromRunToDone) { | |
200 if (!FLAG_incremental_marking) return; | |
201 | |
202 MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState()); | |
203 | |
204 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000)); | |
205 EXPECT_EQ(MemoryReducer::kDone, state1.action); | |
206 EXPECT_EQ(0, state1.next_gc_start_ms); | |
207 EXPECT_EQ(0, state1.started_gcs); | |
208 | |
209 state0.started_gcs = MemoryReducer::kMaxNumberOfGCs; | |
210 | |
211 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000)); | |
212 EXPECT_EQ(MemoryReducer::kDone, state1.action); | |
213 EXPECT_EQ(0, state1.next_gc_start_ms); | |
214 EXPECT_EQ(0, state1.started_gcs); | |
215 } | |
216 | |
217 | |
218 TEST(MemoryReducer, FromRunToWait) { | |
219 if (!FLAG_incremental_marking) return; | |
220 | |
221 MemoryReducer::State state0(RunState(2, 0.0)), state1(DoneState()); | |
222 | |
223 state1 = MemoryReducer::Step(state0, MarkCompactEventGarbageLeft(2000)); | |
224 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
225 EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms); | |
226 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
227 | |
228 state0.started_gcs = 1; | |
229 | |
230 state1 = MemoryReducer::Step(state0, MarkCompactEventNoGarbageLeft(2000)); | |
231 EXPECT_EQ(MemoryReducer::kWait, state1.action); | |
232 EXPECT_EQ(2000 + MemoryReducer::kShortDelayMs, state1.next_gc_start_ms); | |
233 EXPECT_EQ(state0.started_gcs, state1.started_gcs); | |
234 } | |
235 | |
236 } // namespace internal | |
237 } // namespace v8 | |
OLD | NEW |