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 "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #include "src/gc-tracer.h" | 7 #include "src/gc-tracer.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 14 matching lines...) Expand all Loading... | |
25 gc_reason(gc_reason), | 25 gc_reason(gc_reason), |
26 collector_reason(collector_reason), | 26 collector_reason(collector_reason), |
27 start_time(0.0), | 27 start_time(0.0), |
28 end_time(0.0), | 28 end_time(0.0), |
29 start_object_size(0), | 29 start_object_size(0), |
30 end_object_size(0), | 30 end_object_size(0), |
31 start_memory_size(0), | 31 start_memory_size(0), |
32 end_memory_size(0), | 32 end_memory_size(0), |
33 start_holes_size(0), | 33 start_holes_size(0), |
34 end_holes_size(0), | 34 end_holes_size(0), |
35 cumulative_incremental_marking_steps(0), | |
35 incremental_marking_steps(0), | 36 incremental_marking_steps(0), |
36 incremental_marking_duration(0.0) { | 37 cumulative_incremental_marking_bytes(0), |
38 incremental_marking_bytes(0), | |
39 cumulative_incremental_marking_duration(0.0), | |
40 incremental_marking_duration(0.0), | |
41 longest_incremental_marking_step(0.0) { | |
37 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { | 42 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { |
38 scopes[i] = 0; | 43 scopes[i] = 0; |
39 } | 44 } |
40 } | 45 } |
41 | 46 |
42 | 47 |
43 const char* GCTracer::Event::TypeName(bool short_name) const { | 48 const char* GCTracer::Event::TypeName(bool short_name) const { |
44 switch (type) { | 49 switch (type) { |
45 case SCAVENGER: | 50 case SCAVENGER: |
46 if (short_name) { | 51 if (short_name) { |
(...skipping 13 matching lines...) Expand all Loading... | |
60 } else { | 65 } else { |
61 return "Start"; | 66 return "Start"; |
62 } | 67 } |
63 } | 68 } |
64 return "Unknown Event Type"; | 69 return "Unknown Event Type"; |
65 } | 70 } |
66 | 71 |
67 | 72 |
68 GCTracer::GCTracer(Heap* heap) | 73 GCTracer::GCTracer(Heap* heap) |
69 : heap_(heap), | 74 : heap_(heap), |
70 incremental_marking_steps_(0), | 75 cumulative_incremental_marking_steps_(0), |
71 incremental_marking_duration_(0.0), | 76 cumulative_incremental_marking_bytes_(0), |
77 cumulative_incremental_marking_duration_(0.0), | |
72 longest_incremental_marking_step_(0.0) { | 78 longest_incremental_marking_step_(0.0) { |
73 current_ = Event(Event::START, NULL, NULL); | 79 current_ = Event(Event::START, NULL, NULL); |
74 current_.end_time = base::OS::TimeCurrentMillis(); | 80 current_.end_time = base::OS::TimeCurrentMillis(); |
75 previous_ = previous_mark_compactor_event_ = current_; | 81 previous_ = previous_mark_compactor_event_ = current_; |
76 } | 82 } |
77 | 83 |
78 | 84 |
79 void GCTracer::Start(GarbageCollector collector, const char* gc_reason, | 85 void GCTracer::Start(GarbageCollector collector, const char* gc_reason, |
80 const char* collector_reason) { | 86 const char* collector_reason) { |
81 previous_ = current_; | 87 previous_ = current_; |
82 if (current_.type == Event::MARK_COMPACTOR) | 88 if (current_.type == Event::MARK_COMPACTOR) |
83 previous_mark_compactor_event_ = current_; | 89 previous_mark_compactor_event_ = current_; |
84 | 90 |
85 if (collector == SCAVENGER) { | 91 if (collector == SCAVENGER) { |
86 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); | 92 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); |
87 } else { | 93 } else { |
88 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); | 94 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); |
89 } | 95 } |
90 | 96 |
91 current_.start_time = base::OS::TimeCurrentMillis(); | 97 current_.start_time = base::OS::TimeCurrentMillis(); |
92 current_.start_object_size = heap_->SizeOfObjects(); | 98 current_.start_object_size = heap_->SizeOfObjects(); |
93 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); | 99 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); |
94 current_.start_holes_size = CountTotalHolesSize(heap_); | 100 current_.start_holes_size = CountTotalHolesSize(heap_); |
95 | 101 |
96 current_.incremental_marking_steps = incremental_marking_steps_; | 102 current_.cumulative_incremental_marking_steps = |
97 current_.incremental_marking_duration = incremental_marking_duration_; | 103 cumulative_incremental_marking_steps_; |
104 current_.cumulative_incremental_marking_bytes = | |
105 cumulative_incremental_marking_bytes_; | |
106 current_.cumulative_incremental_marking_duration = | |
107 cumulative_incremental_marking_duration_; | |
98 current_.longest_incremental_marking_step = longest_incremental_marking_step_; | 108 current_.longest_incremental_marking_step = longest_incremental_marking_step_; |
99 | 109 |
100 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { | 110 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { |
101 current_.scopes[i] = 0; | 111 current_.scopes[i] = 0; |
102 } | 112 } |
103 } | 113 } |
104 | 114 |
105 | 115 |
106 void GCTracer::Stop() { | 116 void GCTracer::Stop() { |
107 current_.end_time = base::OS::TimeCurrentMillis(); | 117 current_.end_time = base::OS::TimeCurrentMillis(); |
108 current_.end_object_size = heap_->SizeOfObjects(); | 118 current_.end_object_size = heap_->SizeOfObjects(); |
109 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); | 119 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); |
110 current_.end_holes_size = CountTotalHolesSize(heap_); | 120 current_.end_holes_size = CountTotalHolesSize(heap_); |
111 | 121 |
112 if (current_.type == Event::SCAVENGER) { | 122 if (current_.type == Event::SCAVENGER) { |
113 scavenger_events_.push_front(current_); | 123 scavenger_events_.push_front(current_); |
124 current_.incremental_marking_steps = | |
125 current_.cumulative_incremental_marking_steps - | |
126 previous_.cumulative_incremental_marking_steps; | |
127 current_.incremental_marking_bytes = | |
128 current_.cumulative_incremental_marking_bytes - | |
129 previous_.cumulative_incremental_marking_bytes; | |
130 current_.incremental_marking_duration = | |
131 current_.cumulative_incremental_marking_duration - | |
132 previous_.cumulative_incremental_marking_duration; | |
114 } else { | 133 } else { |
115 mark_compactor_events_.push_front(current_); | 134 mark_compactor_events_.push_front(current_); |
135 current_.incremental_marking_steps = | |
136 current_.cumulative_incremental_marking_steps - | |
137 previous_mark_compactor_event_.cumulative_incremental_marking_steps; | |
138 current_.incremental_marking_bytes = | |
139 current_.cumulative_incremental_marking_bytes - | |
140 previous_mark_compactor_event_.cumulative_incremental_marking_bytes; | |
141 current_.incremental_marking_duration = | |
142 current_.cumulative_incremental_marking_duration - | |
143 previous_mark_compactor_event_.cumulative_incremental_marking_duration; | |
144 longest_incremental_marking_step_ = 0.0; | |
116 } | 145 } |
117 | 146 |
118 if (current_.type == Event::MARK_COMPACTOR) | |
119 longest_incremental_marking_step_ = 0.0; | |
120 | |
121 // TODO(ernstm): move the code below out of GCTracer. | 147 // TODO(ernstm): move the code below out of GCTracer. |
122 | 148 |
123 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; | 149 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; |
124 | 150 |
125 double duration = current_.end_time - current_.start_time; | 151 double duration = current_.end_time - current_.start_time; |
126 double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0); | 152 double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0); |
127 | 153 |
128 heap_->UpdateCumulativeGCStatistics(duration, spent_in_mutator, | 154 heap_->UpdateCumulativeGCStatistics(duration, spent_in_mutator, |
129 current_.scopes[Scope::MC_MARK]); | 155 current_.scopes[Scope::MC_MARK]); |
130 | 156 |
131 if (current_.type == Event::SCAVENGER && FLAG_trace_gc_ignore_scavenger) | 157 if (current_.type == Event::SCAVENGER && FLAG_trace_gc_ignore_scavenger) |
132 return; | 158 return; |
133 | 159 |
134 if (FLAG_trace_gc) { | 160 if (FLAG_trace_gc) { |
135 if (FLAG_trace_gc_nvp) | 161 if (FLAG_trace_gc_nvp) |
136 PrintNVP(); | 162 PrintNVP(); |
137 else | 163 else |
138 Print(); | 164 Print(); |
139 | 165 |
140 heap_->PrintShortHeapStatistics(); | 166 heap_->PrintShortHeapStatistics(); |
141 } | 167 } |
142 } | 168 } |
143 | 169 |
144 | 170 |
145 void GCTracer::AddIncrementalMarkingStep(double duration) { | 171 void GCTracer::AddIncrementalMarkingStep(double duration, intptr_t bytes) { |
146 incremental_marking_steps_++; | 172 cumulative_incremental_marking_steps_++; |
147 incremental_marking_duration_ += duration; | 173 cumulative_incremental_marking_bytes_ += bytes; |
174 cumulative_incremental_marking_duration_ += duration; | |
148 longest_incremental_marking_step_ = | 175 longest_incremental_marking_step_ = |
149 Max(longest_incremental_marking_step_, duration); | 176 Max(longest_incremental_marking_step_, duration); |
150 } | 177 } |
151 | 178 |
152 | 179 |
153 void GCTracer::Print() const { | 180 void GCTracer::Print() const { |
154 PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init()); | 181 PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init()); |
155 | 182 |
156 PrintF("%s %.1f (%.1f) -> %.1f (%.1f) MB, ", current_.TypeName(false), | 183 PrintF("%s %.1f (%.1f) -> %.1f (%.1f) MB, ", current_.TypeName(false), |
157 static_cast<double>(current_.start_object_size) / MB, | 184 static_cast<double>(current_.start_object_size) / MB, |
158 static_cast<double>(current_.start_memory_size) / MB, | 185 static_cast<double>(current_.start_memory_size) / MB, |
159 static_cast<double>(current_.end_object_size) / MB, | 186 static_cast<double>(current_.end_object_size) / MB, |
160 static_cast<double>(current_.end_memory_size) / MB); | 187 static_cast<double>(current_.end_memory_size) / MB); |
161 | 188 |
162 int external_time = static_cast<int>(current_.scopes[Scope::EXTERNAL]); | 189 int external_time = static_cast<int>(current_.scopes[Scope::EXTERNAL]); |
163 if (external_time > 0) PrintF("%d / ", external_time); | 190 if (external_time > 0) PrintF("%d / ", external_time); |
164 | 191 |
165 double duration = current_.end_time - current_.start_time; | 192 double duration = current_.end_time - current_.start_time; |
166 PrintF("%.1f ms", duration); | 193 PrintF("%.1f ms", duration); |
167 if (current_.type == Event::SCAVENGER) { | 194 if (current_.type == Event::SCAVENGER) { |
168 int steps = current_.incremental_marking_steps - | 195 if (current_.incremental_marking_steps > 0) { |
169 previous_.incremental_marking_steps; | |
170 if (steps > 0) { | |
171 PrintF(" (+ %.1f ms in %d steps since last GC)", | 196 PrintF(" (+ %.1f ms in %d steps since last GC)", |
172 current_.incremental_marking_duration - | 197 current_.incremental_marking_duration, |
173 previous_.incremental_marking_duration, | 198 current_.incremental_marking_steps); |
174 steps); | |
175 } | 199 } |
176 } else { | 200 } else { |
177 int steps = current_.incremental_marking_steps - | 201 if (current_.incremental_marking_steps > 0) { |
178 previous_mark_compactor_event_.incremental_marking_steps; | |
179 if (steps > 0) { | |
180 PrintF( | 202 PrintF( |
181 " (+ %.1f ms in %d steps since start of marking, " | 203 " (+ %.1f ms in %d steps since start of marking, " |
182 "biggest step %.1f ms)", | 204 "biggest step %.1f ms)", |
183 current_.incremental_marking_duration - | 205 current_.incremental_marking_duration, |
184 previous_mark_compactor_event_.incremental_marking_duration, | 206 current_.incremental_marking_steps, |
185 steps, current_.longest_incremental_marking_step); | 207 current_.longest_incremental_marking_step); |
186 } | 208 } |
187 } | 209 } |
188 | 210 |
189 if (current_.gc_reason != NULL) { | 211 if (current_.gc_reason != NULL) { |
190 PrintF(" [%s]", current_.gc_reason); | 212 PrintF(" [%s]", current_.gc_reason); |
191 } | 213 } |
192 | 214 |
193 if (current_.collector_reason != NULL) { | 215 if (current_.collector_reason != NULL) { |
194 PrintF(" [%s]", current_.collector_reason); | 216 PrintF(" [%s]", current_.collector_reason); |
195 } | 217 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 PrintF("promoted=%" V8_PTR_PREFIX "d ", heap_->promoted_objects_size_); | 267 PrintF("promoted=%" V8_PTR_PREFIX "d ", heap_->promoted_objects_size_); |
246 PrintF("semi_space_copied=%" V8_PTR_PREFIX "d ", | 268 PrintF("semi_space_copied=%" V8_PTR_PREFIX "d ", |
247 heap_->semi_space_copied_object_size_); | 269 heap_->semi_space_copied_object_size_); |
248 PrintF("nodes_died_in_new=%d ", heap_->nodes_died_in_new_space_); | 270 PrintF("nodes_died_in_new=%d ", heap_->nodes_died_in_new_space_); |
249 PrintF("nodes_copied_in_new=%d ", heap_->nodes_copied_in_new_space_); | 271 PrintF("nodes_copied_in_new=%d ", heap_->nodes_copied_in_new_space_); |
250 PrintF("nodes_promoted=%d ", heap_->nodes_promoted_); | 272 PrintF("nodes_promoted=%d ", heap_->nodes_promoted_); |
251 PrintF("promotion_rate=%.1f%% ", heap_->promotion_rate_); | 273 PrintF("promotion_rate=%.1f%% ", heap_->promotion_rate_); |
252 PrintF("semi_space_copy_rate=%.1f%% ", heap_->semi_space_copied_rate_); | 274 PrintF("semi_space_copy_rate=%.1f%% ", heap_->semi_space_copied_rate_); |
253 | 275 |
254 if (current_.type == Event::SCAVENGER) { | 276 if (current_.type == Event::SCAVENGER) { |
255 PrintF("stepscount=%d ", current_.incremental_marking_steps - | 277 PrintF("stepscount=%d ", current_.incremental_marking_steps); |
Hannes Payer (out of office)
2014/07/28 13:04:12
Since you are here, can we make the names here uni
ernstm
2014/07/28 14:43:26
Done.
| |
256 previous_.incremental_marking_steps); | 278 PrintF("stepstook=%.1f ", current_.incremental_marking_duration); |
257 PrintF("stepstook=%.1f ", current_.incremental_marking_duration - | |
258 previous_.incremental_marking_duration); | |
259 } else { | 279 } else { |
260 PrintF("stepscount=%d ", | 280 PrintF("stepscount=%d ", current_.incremental_marking_steps); |
261 current_.incremental_marking_steps - | 281 PrintF("stepstook=%.1f ", current_.incremental_marking_duration); |
262 previous_mark_compactor_event_.incremental_marking_steps); | |
263 PrintF("stepstook=%.1f ", | |
264 current_.incremental_marking_duration - | |
265 previous_mark_compactor_event_.incremental_marking_duration); | |
266 PrintF("longeststep=%.1f ", current_.longest_incremental_marking_step); | 282 PrintF("longeststep=%.1f ", current_.longest_incremental_marking_step); |
Hannes Payer (out of office)
2014/07/28 13:04:12
Let's print the MarkingSpeedInBytesPerMillisecond
ernstm
2014/07/28 14:43:26
Done.
| |
267 } | 283 } |
268 | 284 |
269 PrintF("\n"); | 285 PrintF("\n"); |
270 } | 286 } |
271 | 287 |
272 | 288 |
273 double GCTracer::MeanDuration(const EventBuffer& events) const { | 289 double GCTracer::MeanDuration(const EventBuffer& events) const { |
274 if (events.empty()) return 0.0; | 290 if (events.empty()) return 0.0; |
275 | 291 |
276 double mean = 0.0; | 292 double mean = 0.0; |
(...skipping 15 matching lines...) Expand all Loading... | |
292 while (iter != events.end()) { | 308 while (iter != events.end()) { |
293 maximum = Max(iter->end_time - iter->start_time, maximum); | 309 maximum = Max(iter->end_time - iter->start_time, maximum); |
294 ++iter; | 310 ++iter; |
295 } | 311 } |
296 | 312 |
297 return maximum; | 313 return maximum; |
298 } | 314 } |
299 | 315 |
300 | 316 |
301 double GCTracer::MeanIncrementalMarkingDuration() const { | 317 double GCTracer::MeanIncrementalMarkingDuration() const { |
302 if (mark_compactor_events_.empty()) return 0.0; | 318 if (cumulative_incremental_marking_steps_ == 0) return 0.0; |
303 | 319 |
304 EventBuffer::const_iterator last_mc = mark_compactor_events_.begin(); | 320 // We haven't complete an entire round of incremental marking, yet. |
Hannes Payer (out of office)
2014/07/28 13:04:12
completed
ernstm
2014/07/28 14:43:26
Done.
| |
305 return last_mc->incremental_marking_duration / | 321 // Use data from GCTracer instead of data from event buffers. |
306 last_mc->incremental_marking_steps; | 322 if (mark_compactor_events_.empty()) { |
323 return cumulative_incremental_marking_duration_ / | |
324 cumulative_incremental_marking_steps_; | |
325 } | |
326 | |
327 int steps = 0; | |
328 double durations = 0.0; | |
329 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); | |
330 while (iter != mark_compactor_events_.end()) { | |
331 steps += iter->incremental_marking_steps; | |
332 durations += iter->incremental_marking_duration; | |
333 ++iter; | |
334 } | |
335 | |
336 if (steps == 0) return 0.0; | |
337 | |
338 return durations / steps; | |
307 } | 339 } |
308 | 340 |
309 | 341 |
310 double GCTracer::MaxIncrementalMarkingDuration() const { | 342 double GCTracer::MaxIncrementalMarkingDuration() const { |
311 if (mark_compactor_events_.empty()) return 0.0; | 343 // We haven't complete an entire round of incremental marking, yet. |
Hannes Payer (out of office)
2014/07/28 13:04:13
completed
ernstm
2014/07/28 14:43:26
Done.
| |
344 // Use data from GCTracer instead of data from event buffers. | |
345 if (mark_compactor_events_.empty()) return longest_incremental_marking_step_; | |
312 | 346 |
313 EventBuffer::const_iterator last_mc = mark_compactor_events_.begin(); | 347 double max_duration = 0.0; |
314 return last_mc->longest_incremental_marking_step; | 348 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); |
349 while (iter != mark_compactor_events_.end()) | |
350 max_duration = Max(iter->longest_incremental_marking_step, max_duration); | |
351 | |
352 return max_duration; | |
353 } | |
354 | |
355 | |
356 double GCTracer::MarkingSpeedInBytesPerMillisecond() const { | |
357 if (cumulative_incremental_marking_duration_ == 0.0) return 0.0; | |
358 | |
359 // We haven't complete an entire round of incremental marking, yet. | |
360 // Use data from GCTracer instead of data from event buffers. | |
361 if (mark_compactor_events_.empty()) { | |
362 return cumulative_incremental_marking_bytes_ / | |
363 cumulative_incremental_marking_duration_; | |
364 } | |
365 | |
366 intptr_t bytes = 0; | |
367 double durations = 0.0; | |
368 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); | |
369 while (iter != mark_compactor_events_.end()) { | |
370 bytes += iter->incremental_marking_bytes; | |
371 durations += iter->incremental_marking_duration; | |
372 ++iter; | |
373 } | |
374 | |
375 if (durations == 0.0) return 0.0; | |
376 | |
377 return bytes / durations; | |
315 } | 378 } |
316 } | 379 } |
317 } // namespace v8::internal | 380 } // namespace v8::internal |
OLD | NEW |