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) { |
| 123 current_.incremental_marking_steps = |
| 124 current_.cumulative_incremental_marking_steps - |
| 125 previous_.cumulative_incremental_marking_steps; |
| 126 current_.incremental_marking_bytes = |
| 127 current_.cumulative_incremental_marking_bytes - |
| 128 previous_.cumulative_incremental_marking_bytes; |
| 129 current_.incremental_marking_duration = |
| 130 current_.cumulative_incremental_marking_duration - |
| 131 previous_.cumulative_incremental_marking_duration; |
113 scavenger_events_.push_front(current_); | 132 scavenger_events_.push_front(current_); |
114 } else { | 133 } else { |
| 134 current_.incremental_marking_steps = |
| 135 current_.cumulative_incremental_marking_steps - |
| 136 previous_mark_compactor_event_.cumulative_incremental_marking_steps; |
| 137 current_.incremental_marking_bytes = |
| 138 current_.cumulative_incremental_marking_bytes - |
| 139 previous_mark_compactor_event_.cumulative_incremental_marking_bytes; |
| 140 current_.incremental_marking_duration = |
| 141 current_.cumulative_incremental_marking_duration - |
| 142 previous_mark_compactor_event_.cumulative_incremental_marking_duration; |
| 143 longest_incremental_marking_step_ = 0.0; |
115 mark_compactor_events_.push_front(current_); | 144 mark_compactor_events_.push_front(current_); |
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("steps_count=%d ", current_.incremental_marking_steps); |
256 previous_.incremental_marking_steps); | 278 PrintF("steps_took=%.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("steps_count=%d ", current_.incremental_marking_steps); |
261 current_.incremental_marking_steps - | 281 PrintF("steps_took=%.1f ", current_.incremental_marking_duration); |
262 previous_mark_compactor_event_.incremental_marking_steps); | 282 PrintF("longest_step=%.1f ", current_.longest_incremental_marking_step); |
263 PrintF("stepstook=%.1f ", | 283 PrintF("marking_throughput=%d\n", MarkingSpeedInBytesPerMillisecond()); |
264 current_.incremental_marking_duration - | |
265 previous_mark_compactor_event_.incremental_marking_duration); | |
266 PrintF("longeststep=%.1f ", current_.longest_incremental_marking_step); | |
267 } | 284 } |
268 | 285 |
269 PrintF("\n"); | 286 PrintF("\n"); |
270 } | 287 } |
271 | 288 |
272 | 289 |
273 double GCTracer::MeanDuration(const EventBuffer& events) const { | 290 double GCTracer::MeanDuration(const EventBuffer& events) const { |
274 if (events.empty()) return 0.0; | 291 if (events.empty()) return 0.0; |
275 | 292 |
276 double mean = 0.0; | 293 double mean = 0.0; |
(...skipping 15 matching lines...) Expand all Loading... |
292 while (iter != events.end()) { | 309 while (iter != events.end()) { |
293 maximum = Max(iter->end_time - iter->start_time, maximum); | 310 maximum = Max(iter->end_time - iter->start_time, maximum); |
294 ++iter; | 311 ++iter; |
295 } | 312 } |
296 | 313 |
297 return maximum; | 314 return maximum; |
298 } | 315 } |
299 | 316 |
300 | 317 |
301 double GCTracer::MeanIncrementalMarkingDuration() const { | 318 double GCTracer::MeanIncrementalMarkingDuration() const { |
302 if (mark_compactor_events_.empty()) return 0.0; | 319 if (cumulative_incremental_marking_steps_ == 0) return 0.0; |
303 | 320 |
304 EventBuffer::const_iterator last_mc = mark_compactor_events_.begin(); | 321 // We haven't completed an entire round of incremental marking, yet. |
305 return last_mc->incremental_marking_duration / | 322 // Use data from GCTracer instead of data from event buffers. |
306 last_mc->incremental_marking_steps; | 323 if (mark_compactor_events_.empty()) { |
| 324 return cumulative_incremental_marking_duration_ / |
| 325 cumulative_incremental_marking_steps_; |
| 326 } |
| 327 |
| 328 int steps = 0; |
| 329 double durations = 0.0; |
| 330 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); |
| 331 while (iter != mark_compactor_events_.end()) { |
| 332 steps += iter->incremental_marking_steps; |
| 333 durations += iter->incremental_marking_duration; |
| 334 ++iter; |
| 335 } |
| 336 |
| 337 if (steps == 0) return 0.0; |
| 338 |
| 339 return durations / steps; |
307 } | 340 } |
308 | 341 |
309 | 342 |
310 double GCTracer::MaxIncrementalMarkingDuration() const { | 343 double GCTracer::MaxIncrementalMarkingDuration() const { |
311 if (mark_compactor_events_.empty()) return 0.0; | 344 // We haven't completed an entire round of incremental marking, yet. |
| 345 // Use data from GCTracer instead of data from event buffers. |
| 346 if (mark_compactor_events_.empty()) return longest_incremental_marking_step_; |
312 | 347 |
313 EventBuffer::const_iterator last_mc = mark_compactor_events_.begin(); | 348 double max_duration = 0.0; |
314 return last_mc->longest_incremental_marking_step; | 349 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); |
| 350 while (iter != mark_compactor_events_.end()) |
| 351 max_duration = Max(iter->longest_incremental_marking_step, max_duration); |
| 352 |
| 353 return max_duration; |
| 354 } |
| 355 |
| 356 |
| 357 intptr_t GCTracer::MarkingSpeedInBytesPerMillisecond() const { |
| 358 if (cumulative_incremental_marking_duration_ == 0.0) return 0; |
| 359 |
| 360 // We haven't completed an entire round of incremental marking, yet. |
| 361 // Use data from GCTracer instead of data from event buffers. |
| 362 if (mark_compactor_events_.empty()) { |
| 363 return static_cast<intptr_t>(cumulative_incremental_marking_bytes_ / |
| 364 cumulative_incremental_marking_duration_); |
| 365 } |
| 366 |
| 367 intptr_t bytes = 0; |
| 368 double durations = 0.0; |
| 369 EventBuffer::const_iterator iter = mark_compactor_events_.begin(); |
| 370 while (iter != mark_compactor_events_.end()) { |
| 371 bytes += iter->incremental_marking_bytes; |
| 372 durations += iter->incremental_marking_duration; |
| 373 ++iter; |
| 374 } |
| 375 |
| 376 if (durations == 0.0) return 0; |
| 377 |
| 378 return static_cast<intptr_t>(bytes / durations); |
315 } | 379 } |
316 } | 380 } |
317 } // namespace v8::internal | 381 } // namespace v8::internal |
OLD | NEW |