OLD | NEW |
---|---|
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 "src/heap/memory-reducer.h" | 5 #include "src/heap/memory-reducer.h" |
6 | 6 |
7 #include "src/flags.h" | 7 #include "src/flags.h" |
8 #include "src/heap/heap.h" | 8 #include "src/heap/heap.h" |
9 #include "src/utils.h" | 9 #include "src/utils.h" |
10 #include "src/v8.h" | 10 #include "src/v8.h" |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 const int MemoryReducer::kLongDelayMs = 5000; | 15 const int MemoryReducer::kLongDelayMs = 5000; |
16 const int MemoryReducer::kShortDelayMs = 500; | 16 const int MemoryReducer::kShortDelayMs = 500; |
17 const int MemoryReducer::kWatchdogDelayMs = 100000; | |
17 const int MemoryReducer::kMaxNumberOfGCs = 3; | 18 const int MemoryReducer::kMaxNumberOfGCs = 3; |
18 | 19 |
19 MemoryReducer::TimerTask::TimerTask(MemoryReducer* memory_reducer) | 20 MemoryReducer::TimerTask::TimerTask(MemoryReducer* memory_reducer) |
20 : CancelableTask(memory_reducer->heap()->isolate()), | 21 : CancelableTask(memory_reducer->heap()->isolate()), |
21 memory_reducer_(memory_reducer) {} | 22 memory_reducer_(memory_reducer) {} |
22 | 23 |
23 | 24 |
24 void MemoryReducer::TimerTask::RunInternal() { | 25 void MemoryReducer::TimerTask::RunInternal() { |
25 Heap* heap = memory_reducer_->heap(); | 26 Heap* heap = memory_reducer_->heap(); |
26 Event event; | 27 Event event; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
103 state_.started_gcs); | 104 state_.started_gcs); |
104 } | 105 } |
105 } | 106 } |
106 } | 107 } |
107 | 108 |
108 | 109 |
109 // For specification of this function see the comment for MemoryReducer class. | 110 // For specification of this function see the comment for MemoryReducer class. |
110 MemoryReducer::State MemoryReducer::Step(const State& state, | 111 MemoryReducer::State MemoryReducer::Step(const State& state, |
111 const Event& event) { | 112 const Event& event) { |
112 if (!FLAG_incremental_marking) { | 113 if (!FLAG_incremental_marking) { |
113 return State(kDone, 0, 0); | 114 return State(kDone, 0, 0, state.last_gc_time_ms); |
114 } | 115 } |
115 switch (state.action) { | 116 switch (state.action) { |
116 case kDone: | 117 case kDone: |
117 if (event.type == kTimer || event.type == kBackgroundIdleNotification) { | 118 if (event.type == kTimer || event.type == kBackgroundIdleNotification) { |
118 return state; | 119 return state; |
119 } else { | 120 } else { |
120 DCHECK(event.type == kContextDisposed || event.type == kMarkCompact); | 121 DCHECK(event.type == kContextDisposed || event.type == kMarkCompact); |
121 return State(kWait, 0, event.time_ms + kLongDelayMs); | 122 return State( |
123 kWait, 0, event.time_ms + kLongDelayMs, | |
124 event.type == kMarkCompact ? event.time_ms : state.last_gc_time_ms); | |
122 } | 125 } |
123 case kWait: | 126 case kWait: |
124 switch (event.type) { | 127 switch (event.type) { |
125 case kContextDisposed: | 128 case kContextDisposed: |
126 return state; | 129 return state; |
127 case kTimer: | 130 case kTimer: |
128 if (state.started_gcs >= kMaxNumberOfGCs) { | 131 if (state.started_gcs >= kMaxNumberOfGCs) { |
129 return State(kDone, 0, 0.0); | 132 return State(kDone, 0, 0.0, state.last_gc_time_ms); |
130 } else if (event.can_start_incremental_gc && | 133 } else if (event.can_start_incremental_gc && |
131 event.low_allocation_rate) { | 134 (event.low_allocation_rate || |
135 (state.last_gc_time_ms != 0 && | |
ulan
2015/07/30 13:20:19
This is the main change.
Other lines in this func
Hannes Payer (out of office)
2015/07/30 14:28:03
Can we make the watchdog part a boolean function t
ulan
2015/07/31 09:47:43
Done.
| |
136 event.time_ms > | |
137 state.last_gc_time_ms + kWatchdogDelayMs))) { | |
132 if (state.next_gc_start_ms <= event.time_ms) { | 138 if (state.next_gc_start_ms <= event.time_ms) { |
133 return State(kRun, state.started_gcs + 1, 0.0); | 139 return State(kRun, state.started_gcs + 1, 0.0, |
140 state.last_gc_time_ms); | |
134 } else { | 141 } else { |
135 return state; | 142 return state; |
136 } | 143 } |
137 } else { | 144 } else { |
138 return State(kWait, state.started_gcs, | 145 return State(kWait, state.started_gcs, event.time_ms + kLongDelayMs, |
139 event.time_ms + kLongDelayMs); | 146 state.last_gc_time_ms); |
140 } | 147 } |
141 case kBackgroundIdleNotification: | 148 case kBackgroundIdleNotification: |
142 if (event.can_start_incremental_gc && | 149 if (event.can_start_incremental_gc && |
143 state.started_gcs < kMaxNumberOfGCs) { | 150 state.started_gcs < kMaxNumberOfGCs) { |
144 return State(kWait, state.started_gcs + 1, | 151 return State(kWait, state.started_gcs + 1, |
145 event.time_ms + kLongDelayMs); | 152 event.time_ms + kLongDelayMs, state.last_gc_time_ms); |
146 } else { | 153 } else { |
147 return state; | 154 return state; |
148 } | 155 } |
149 case kMarkCompact: | 156 case kMarkCompact: |
150 return State(kWait, state.started_gcs, event.time_ms + kLongDelayMs); | 157 return State(kWait, state.started_gcs, event.time_ms + kLongDelayMs, |
158 event.time_ms); | |
151 } | 159 } |
152 case kRun: | 160 case kRun: |
153 if (event.type != kMarkCompact) { | 161 if (event.type != kMarkCompact) { |
154 return state; | 162 return state; |
155 } else { | 163 } else { |
156 if (state.started_gcs < kMaxNumberOfGCs && | 164 if (state.started_gcs < kMaxNumberOfGCs && |
157 (event.next_gc_likely_to_collect_more || state.started_gcs == 1)) { | 165 (event.next_gc_likely_to_collect_more || state.started_gcs == 1)) { |
158 return State(kWait, state.started_gcs, event.time_ms + kShortDelayMs); | 166 return State(kWait, state.started_gcs, event.time_ms + kShortDelayMs, |
167 event.time_ms); | |
159 } else { | 168 } else { |
160 return State(kDone, 0, 0.0); | 169 return State(kDone, 0, 0.0, event.time_ms); |
161 } | 170 } |
162 } | 171 } |
163 } | 172 } |
164 UNREACHABLE(); | 173 UNREACHABLE(); |
165 return State(kDone, 0, 0); // Make the compiler happy. | 174 return State(kDone, 0, 0, 0.0); // Make the compiler happy. |
166 } | 175 } |
167 | 176 |
168 | 177 |
169 void MemoryReducer::ScheduleTimer(double delay_ms) { | 178 void MemoryReducer::ScheduleTimer(double delay_ms) { |
170 DCHECK(delay_ms > 0); | 179 DCHECK(delay_ms > 0); |
171 // Leave some room for precision error in task scheduler. | 180 // Leave some room for precision error in task scheduler. |
172 const double kSlackMs = 100; | 181 const double kSlackMs = 100; |
173 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap()->isolate()); | 182 v8::Isolate* isolate = reinterpret_cast<v8::Isolate*>(heap()->isolate()); |
174 auto timer_task = new MemoryReducer::TimerTask(this); | 183 auto timer_task = new MemoryReducer::TimerTask(this); |
175 V8::GetCurrentPlatform()->CallDelayedOnForegroundThread( | 184 V8::GetCurrentPlatform()->CallDelayedOnForegroundThread( |
176 isolate, timer_task, (delay_ms + kSlackMs) / 1000.0); | 185 isolate, timer_task, (delay_ms + kSlackMs) / 1000.0); |
177 } | 186 } |
178 | 187 |
179 | 188 |
180 void MemoryReducer::TearDown() { | 189 void MemoryReducer::TearDown() { state_ = State(kDone, 0, 0, 0.0); } |
181 state_ = State(kDone, 0, 0); | |
182 } | |
183 | 190 |
184 } // internal | 191 } // internal |
185 } // v8 | 192 } // v8 |
OLD | NEW |