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/heap/gc-tracer.h" | 7 #include "src/heap/gc-tracer.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
11 | 11 |
12 static intptr_t CountTotalHolesSize(Heap* heap) { | 12 static intptr_t CountTotalHolesSize(Heap* heap) { |
13 intptr_t holes_size = 0; | 13 intptr_t holes_size = 0; |
14 OldSpaces spaces(heap); | 14 OldSpaces spaces(heap); |
15 for (OldSpace* space = spaces.next(); space != NULL; space = spaces.next()) { | 15 for (OldSpace* space = spaces.next(); space != NULL; space = spaces.next()) { |
16 holes_size += space->Waste() + space->Available(); | 16 holes_size += space->Waste() + space->Available(); |
17 } | 17 } |
18 return holes_size; | 18 return holes_size; |
19 } | 19 } |
20 | 20 |
21 | 21 |
| 22 GCTracer::AllocationEvent::AllocationEvent(double duration, |
| 23 intptr_t allocation_in_bytes) { |
| 24 duration_ = duration; |
| 25 allocation_in_bytes_ = allocation_in_bytes; |
| 26 } |
| 27 |
| 28 |
22 GCTracer::Event::Event(Type type, const char* gc_reason, | 29 GCTracer::Event::Event(Type type, const char* gc_reason, |
23 const char* collector_reason) | 30 const char* collector_reason) |
24 : type(type), | 31 : type(type), |
25 gc_reason(gc_reason), | 32 gc_reason(gc_reason), |
26 collector_reason(collector_reason), | 33 collector_reason(collector_reason), |
27 start_time(0.0), | 34 start_time(0.0), |
28 end_time(0.0), | 35 end_time(0.0), |
29 start_object_size(0), | 36 start_object_size(0), |
30 end_object_size(0), | 37 end_object_size(0), |
31 start_memory_size(0), | 38 start_memory_size(0), |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 | 80 |
74 | 81 |
75 GCTracer::GCTracer(Heap* heap) | 82 GCTracer::GCTracer(Heap* heap) |
76 : heap_(heap), | 83 : heap_(heap), |
77 cumulative_incremental_marking_steps_(0), | 84 cumulative_incremental_marking_steps_(0), |
78 cumulative_incremental_marking_bytes_(0), | 85 cumulative_incremental_marking_bytes_(0), |
79 cumulative_incremental_marking_duration_(0.0), | 86 cumulative_incremental_marking_duration_(0.0), |
80 cumulative_pure_incremental_marking_duration_(0.0), | 87 cumulative_pure_incremental_marking_duration_(0.0), |
81 longest_incremental_marking_step_(0.0), | 88 longest_incremental_marking_step_(0.0), |
82 cumulative_marking_duration_(0.0), | 89 cumulative_marking_duration_(0.0), |
83 cumulative_sweeping_duration_(0.0) { | 90 cumulative_sweeping_duration_(0.0), |
| 91 new_space_top_after_gc_(0) { |
84 current_ = Event(Event::START, NULL, NULL); | 92 current_ = Event(Event::START, NULL, NULL); |
85 current_.end_time = base::OS::TimeCurrentMillis(); | 93 current_.end_time = base::OS::TimeCurrentMillis(); |
86 previous_ = previous_mark_compactor_event_ = current_; | 94 previous_ = previous_mark_compactor_event_ = current_; |
87 } | 95 } |
88 | 96 |
89 | 97 |
90 void GCTracer::Start(GarbageCollector collector, const char* gc_reason, | 98 void GCTracer::Start(GarbageCollector collector, const char* gc_reason, |
91 const char* collector_reason) { | 99 const char* collector_reason) { |
92 previous_ = current_; | 100 previous_ = current_; |
| 101 double start_time = base::OS::TimeCurrentMillis(); |
| 102 if (new_space_top_after_gc_ != 0) { |
| 103 AddNewSpaceAllocationTime( |
| 104 start_time - previous_.end_time, |
| 105 reinterpret_cast<intptr_t>((heap_->new_space()->top()) - |
| 106 new_space_top_after_gc_)); |
| 107 } |
93 if (current_.type == Event::MARK_COMPACTOR) | 108 if (current_.type == Event::MARK_COMPACTOR) |
94 previous_mark_compactor_event_ = current_; | 109 previous_mark_compactor_event_ = current_; |
95 | 110 |
96 if (collector == SCAVENGER) { | 111 if (collector == SCAVENGER) { |
97 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); | 112 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); |
98 } else { | 113 } else { |
99 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); | 114 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); |
100 } | 115 } |
101 | 116 |
102 current_.start_time = base::OS::TimeCurrentMillis(); | 117 current_.start_time = start_time; |
103 current_.start_object_size = heap_->SizeOfObjects(); | 118 current_.start_object_size = heap_->SizeOfObjects(); |
104 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); | 119 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); |
105 current_.start_holes_size = CountTotalHolesSize(heap_); | 120 current_.start_holes_size = CountTotalHolesSize(heap_); |
106 current_.new_space_object_size = | 121 current_.new_space_object_size = |
107 heap_->new_space()->top() - heap_->new_space()->bottom(); | 122 heap_->new_space()->top() - heap_->new_space()->bottom(); |
108 | 123 |
109 current_.cumulative_incremental_marking_steps = | 124 current_.cumulative_incremental_marking_steps = |
110 cumulative_incremental_marking_steps_; | 125 cumulative_incremental_marking_steps_; |
111 current_.cumulative_incremental_marking_bytes = | 126 current_.cumulative_incremental_marking_bytes = |
112 cumulative_incremental_marking_bytes_; | 127 cumulative_incremental_marking_bytes_; |
113 current_.cumulative_incremental_marking_duration = | 128 current_.cumulative_incremental_marking_duration = |
114 cumulative_incremental_marking_duration_; | 129 cumulative_incremental_marking_duration_; |
115 current_.cumulative_pure_incremental_marking_duration = | 130 current_.cumulative_pure_incremental_marking_duration = |
116 cumulative_pure_incremental_marking_duration_; | 131 cumulative_pure_incremental_marking_duration_; |
117 current_.longest_incremental_marking_step = longest_incremental_marking_step_; | 132 current_.longest_incremental_marking_step = longest_incremental_marking_step_; |
118 | 133 |
119 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { | 134 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { |
120 current_.scopes[i] = 0; | 135 current_.scopes[i] = 0; |
121 } | 136 } |
122 } | 137 } |
123 | 138 |
124 | 139 |
125 void GCTracer::Stop() { | 140 void GCTracer::Stop() { |
126 current_.end_time = base::OS::TimeCurrentMillis(); | 141 current_.end_time = base::OS::TimeCurrentMillis(); |
127 current_.end_object_size = heap_->SizeOfObjects(); | 142 current_.end_object_size = heap_->SizeOfObjects(); |
128 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); | 143 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); |
129 current_.end_holes_size = CountTotalHolesSize(heap_); | 144 current_.end_holes_size = CountTotalHolesSize(heap_); |
| 145 new_space_top_after_gc_ = |
| 146 reinterpret_cast<intptr_t>(heap_->new_space()->top()); |
130 | 147 |
131 if (current_.type == Event::SCAVENGER) { | 148 if (current_.type == Event::SCAVENGER) { |
132 current_.incremental_marking_steps = | 149 current_.incremental_marking_steps = |
133 current_.cumulative_incremental_marking_steps - | 150 current_.cumulative_incremental_marking_steps - |
134 previous_.cumulative_incremental_marking_steps; | 151 previous_.cumulative_incremental_marking_steps; |
135 current_.incremental_marking_bytes = | 152 current_.incremental_marking_bytes = |
136 current_.cumulative_incremental_marking_bytes - | 153 current_.cumulative_incremental_marking_bytes - |
137 previous_.cumulative_incremental_marking_bytes; | 154 previous_.cumulative_incremental_marking_bytes; |
138 current_.incremental_marking_duration = | 155 current_.incremental_marking_duration = |
139 current_.cumulative_incremental_marking_duration - | 156 current_.cumulative_incremental_marking_duration - |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 if (FLAG_trace_gc_nvp) | 194 if (FLAG_trace_gc_nvp) |
178 PrintNVP(); | 195 PrintNVP(); |
179 else | 196 else |
180 Print(); | 197 Print(); |
181 | 198 |
182 heap_->PrintShortHeapStatistics(); | 199 heap_->PrintShortHeapStatistics(); |
183 } | 200 } |
184 } | 201 } |
185 | 202 |
186 | 203 |
| 204 void GCTracer::AddNewSpaceAllocationTime(double duration, |
| 205 intptr_t allocation_in_bytes) { |
| 206 allocation_events_.push_front(AllocationEvent(duration, allocation_in_bytes)); |
| 207 } |
| 208 |
| 209 |
187 void GCTracer::AddIncrementalMarkingStep(double duration, intptr_t bytes) { | 210 void GCTracer::AddIncrementalMarkingStep(double duration, intptr_t bytes) { |
188 cumulative_incremental_marking_steps_++; | 211 cumulative_incremental_marking_steps_++; |
189 cumulative_incremental_marking_bytes_ += bytes; | 212 cumulative_incremental_marking_bytes_ += bytes; |
190 cumulative_incremental_marking_duration_ += duration; | 213 cumulative_incremental_marking_duration_ += duration; |
191 longest_incremental_marking_step_ = | 214 longest_incremental_marking_step_ = |
192 Max(longest_incremental_marking_step_, duration); | 215 Max(longest_incremental_marking_step_, duration); |
193 cumulative_marking_duration_ += duration; | 216 cumulative_marking_duration_ += duration; |
194 if (bytes > 0) { | 217 if (bytes > 0) { |
195 cumulative_pure_incremental_marking_duration_ += duration; | 218 cumulative_pure_incremental_marking_duration_ += duration; |
196 } | 219 } |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 current_.start_object_size - previous_.end_object_size; | 310 current_.start_object_size - previous_.end_object_size; |
288 PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc); | 311 PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc); |
289 PrintF("promoted=%" V8_PTR_PREFIX "d ", heap_->promoted_objects_size_); | 312 PrintF("promoted=%" V8_PTR_PREFIX "d ", heap_->promoted_objects_size_); |
290 PrintF("semi_space_copied=%" V8_PTR_PREFIX "d ", | 313 PrintF("semi_space_copied=%" V8_PTR_PREFIX "d ", |
291 heap_->semi_space_copied_object_size_); | 314 heap_->semi_space_copied_object_size_); |
292 PrintF("nodes_died_in_new=%d ", heap_->nodes_died_in_new_space_); | 315 PrintF("nodes_died_in_new=%d ", heap_->nodes_died_in_new_space_); |
293 PrintF("nodes_copied_in_new=%d ", heap_->nodes_copied_in_new_space_); | 316 PrintF("nodes_copied_in_new=%d ", heap_->nodes_copied_in_new_space_); |
294 PrintF("nodes_promoted=%d ", heap_->nodes_promoted_); | 317 PrintF("nodes_promoted=%d ", heap_->nodes_promoted_); |
295 PrintF("promotion_rate=%.1f%% ", heap_->promotion_rate_); | 318 PrintF("promotion_rate=%.1f%% ", heap_->promotion_rate_); |
296 PrintF("semi_space_copy_rate=%.1f%% ", heap_->semi_space_copied_rate_); | 319 PrintF("semi_space_copy_rate=%.1f%% ", heap_->semi_space_copied_rate_); |
| 320 PrintF("new_space_allocation_throughput=%d ", |
| 321 NewSpaceAllocationThroughputInBytesPerMillisecond()); |
297 | 322 |
298 if (current_.type == Event::SCAVENGER) { | 323 if (current_.type == Event::SCAVENGER) { |
299 PrintF("steps_count=%d ", current_.incremental_marking_steps); | 324 PrintF("steps_count=%d ", current_.incremental_marking_steps); |
300 PrintF("steps_took=%.1f ", current_.incremental_marking_duration); | 325 PrintF("steps_took=%.1f ", current_.incremental_marking_duration); |
301 PrintF("scavenge_throughput=%" V8_PTR_PREFIX "d ", | 326 PrintF("scavenge_throughput=%" V8_PTR_PREFIX "d ", |
302 ScavengeSpeedInBytesPerMillisecond()); | 327 ScavengeSpeedInBytesPerMillisecond()); |
303 } else { | 328 } else { |
304 PrintF("steps_count=%d ", current_.incremental_marking_steps); | 329 PrintF("steps_count=%d ", current_.incremental_marking_steps); |
305 PrintF("steps_took=%.1f ", current_.incremental_marking_duration); | 330 PrintF("steps_took=%.1f ", current_.incremental_marking_duration); |
306 PrintF("longest_step=%.1f ", current_.longest_incremental_marking_step); | 331 PrintF("longest_step=%.1f ", current_.longest_incremental_marking_step); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
428 bytes += iter->start_object_size; | 453 bytes += iter->start_object_size; |
429 durations += iter->end_time - iter->start_time + | 454 durations += iter->end_time - iter->start_time + |
430 iter->pure_incremental_marking_duration; | 455 iter->pure_incremental_marking_duration; |
431 ++iter; | 456 ++iter; |
432 } | 457 } |
433 | 458 |
434 if (durations == 0.0) return 0; | 459 if (durations == 0.0) return 0; |
435 | 460 |
436 return static_cast<intptr_t>(bytes / durations); | 461 return static_cast<intptr_t>(bytes / durations); |
437 } | 462 } |
| 463 |
| 464 |
| 465 intptr_t GCTracer::NewSpaceAllocationThroughputInBytesPerMillisecond() const { |
| 466 intptr_t bytes = 0; |
| 467 double durations = 0.0; |
| 468 AllocationEventBuffer::const_iterator iter = allocation_events_.begin(); |
| 469 while (iter != allocation_events_.end()) { |
| 470 bytes += iter->allocation_in_bytes_; |
| 471 durations += iter->duration_; |
| 472 ++iter; |
| 473 } |
| 474 |
| 475 if (durations == 0.0) return 0; |
| 476 |
| 477 return static_cast<intptr_t>(bytes / durations); |
| 478 } |
438 } | 479 } |
439 } // namespace v8::internal | 480 } // namespace v8::internal |
OLD | NEW |