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 "src/v8.h" |
| 6 |
| 7 #include "src/gc-tracer.h" |
| 8 |
| 9 namespace v8 { |
| 10 namespace internal { |
| 11 |
| 12 static intptr_t CountTotalHolesSize(Heap* heap) { |
| 13 intptr_t holes_size = 0; |
| 14 OldSpaces spaces(heap); |
| 15 for (OldSpace* space = spaces.next(); |
| 16 space != NULL; |
| 17 space = spaces.next()) { |
| 18 holes_size += space->Waste() + space->Available(); |
| 19 } |
| 20 return holes_size; |
| 21 } |
| 22 |
| 23 |
| 24 GCTracer::Event::Event(Type type, |
| 25 const char* gc_reason, |
| 26 const char* collector_reason) |
| 27 : type(type), |
| 28 gc_reason(gc_reason), |
| 29 collector_reason(collector_reason), |
| 30 start_time(0.0), |
| 31 end_time(0.0), |
| 32 start_object_size(0), |
| 33 end_object_size(0), |
| 34 start_memory_size(0), |
| 35 end_memory_size(0), |
| 36 start_holes_size(0), |
| 37 end_holes_size(0), |
| 38 incremental_marking_steps(0), |
| 39 incremental_marking_duration(0.0) { |
| 40 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { |
| 41 scopes[i] = 0; |
| 42 } |
| 43 } |
| 44 |
| 45 |
| 46 const char* GCTracer::Event::TypeName(bool short_name) const { |
| 47 switch (type) { |
| 48 case SCAVENGER: |
| 49 if (short_name) { |
| 50 return "s"; |
| 51 } else { |
| 52 return "Scavenge"; |
| 53 } |
| 54 case MARK_COMPACTOR: |
| 55 if (short_name) { |
| 56 return "ms"; |
| 57 } else { |
| 58 return "Mark-sweep"; |
| 59 } |
| 60 case START: |
| 61 if (short_name) { |
| 62 return "st"; |
| 63 } else { |
| 64 return "Start"; |
| 65 } |
| 66 } |
| 67 return "Unknown Event Type"; |
| 68 } |
| 69 |
| 70 |
| 71 GCTracer::GCTracer(Heap* heap) |
| 72 : heap_(heap), |
| 73 incremental_marking_steps_(0), |
| 74 incremental_marking_duration_(0.0), |
| 75 longest_incremental_marking_step_(0.0) { |
| 76 current_ = Event(Event::START, NULL, NULL); |
| 77 current_.end_time = base::OS::TimeCurrentMillis(); |
| 78 previous_ = previous_mark_compactor_event_ = current_; |
| 79 } |
| 80 |
| 81 |
| 82 void GCTracer::Start(GarbageCollector collector, |
| 83 const char* gc_reason, |
| 84 const char* collector_reason) { |
| 85 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; |
| 86 |
| 87 previous_ = current_; |
| 88 if (current_.type == Event::MARK_COMPACTOR) |
| 89 previous_mark_compactor_event_ = current_; |
| 90 |
| 91 if (collector == SCAVENGER) { |
| 92 current_ = Event(Event::SCAVENGER, gc_reason, collector_reason); |
| 93 } else { |
| 94 current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason); |
| 95 } |
| 96 |
| 97 current_.start_time = base::OS::TimeCurrentMillis(); |
| 98 current_.start_object_size = heap_->SizeOfObjects(); |
| 99 current_.start_memory_size = heap_->isolate()->memory_allocator()->Size(); |
| 100 current_.start_holes_size = CountTotalHolesSize(heap_); |
| 101 |
| 102 current_.incremental_marking_steps = incremental_marking_steps_; |
| 103 current_.incremental_marking_duration = incremental_marking_duration_; |
| 104 current_.longest_incremental_marking_step = longest_incremental_marking_step_; |
| 105 |
| 106 for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) { |
| 107 current_.scopes[i] = 0; |
| 108 } |
| 109 } |
| 110 |
| 111 |
| 112 void GCTracer::Stop() { |
| 113 if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return; |
| 114 |
| 115 current_.end_time = base::OS::TimeCurrentMillis(); |
| 116 current_.end_object_size = heap_->SizeOfObjects(); |
| 117 current_.end_memory_size = heap_->isolate()->memory_allocator()->Size(); |
| 118 current_.end_holes_size = CountTotalHolesSize(heap_); |
| 119 |
| 120 if (current_.type == Event::SCAVENGER) { |
| 121 scavenger_events_.push_front(current_); |
| 122 } else { |
| 123 mark_compactor_events_.push_front(current_); |
| 124 } |
| 125 |
| 126 if (current_.type == Event::MARK_COMPACTOR) |
| 127 longest_incremental_marking_step_ = 0.0; |
| 128 |
| 129 double duration = current_.end_time - current_.start_time; |
| 130 double spent_in_mutator = |
| 131 Max(current_.start_time - previous_.end_time, 0.0); |
| 132 |
| 133 heap_->UpdateCumulativeGCStatistics(duration, |
| 134 spent_in_mutator, |
| 135 current_.scopes[Scope::MC_MARK]); |
| 136 |
| 137 if (current_.type == Event::SCAVENGER && FLAG_trace_gc_ignore_scavenger) |
| 138 return; |
| 139 |
| 140 if (FLAG_trace_gc) { |
| 141 if (FLAG_trace_gc_nvp) |
| 142 PrintNVP(); |
| 143 else |
| 144 Print(); |
| 145 |
| 146 heap_->PrintShortHeapStatistics(); |
| 147 } |
| 148 } |
| 149 |
| 150 |
| 151 void GCTracer::AddIncrementalMarkingStep(double duration) { |
| 152 incremental_marking_steps_++; |
| 153 incremental_marking_duration_ += duration; |
| 154 longest_incremental_marking_step_ = |
| 155 Max(longest_incremental_marking_step_, duration); |
| 156 } |
| 157 |
| 158 |
| 159 void GCTracer::Print() const { |
| 160 PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init()); |
| 161 |
| 162 PrintF("%s %.1f (%.1f) -> %.1f (%.1f) MB, ", |
| 163 current_.TypeName(false), |
| 164 static_cast<double>(current_.start_object_size) / MB, |
| 165 static_cast<double>(current_.start_memory_size) / MB, |
| 166 static_cast<double>(current_.end_object_size) / MB, |
| 167 static_cast<double>(current_.end_memory_size) / MB); |
| 168 |
| 169 int external_time = static_cast<int>(current_.scopes[Scope::EXTERNAL]); |
| 170 if (external_time > 0) PrintF("%d / ", external_time); |
| 171 |
| 172 double duration = current_.end_time - current_.start_time; |
| 173 PrintF("%.1f ms", duration); |
| 174 if (current_.type == Event::SCAVENGER) { |
| 175 int steps = current_.incremental_marking_steps - |
| 176 previous_.incremental_marking_steps; |
| 177 if (steps > 0) { |
| 178 PrintF(" (+ %.1f ms in %d steps since last GC)", |
| 179 current_.incremental_marking_duration - |
| 180 previous_.incremental_marking_duration, |
| 181 steps); |
| 182 } |
| 183 } else { |
| 184 int steps = current_.incremental_marking_steps - |
| 185 previous_mark_compactor_event_.incremental_marking_steps; |
| 186 if (steps > 0) { |
| 187 PrintF(" (+ %.1f ms in %d steps since start of marking, " |
| 188 "biggest step %.1f ms)", |
| 189 current_.incremental_marking_duration - |
| 190 previous_mark_compactor_event_.incremental_marking_duration, |
| 191 steps, |
| 192 current_.longest_incremental_marking_step); |
| 193 } |
| 194 } |
| 195 |
| 196 if (current_.gc_reason != NULL) { |
| 197 PrintF(" [%s]", current_.gc_reason); |
| 198 } |
| 199 |
| 200 if (current_.collector_reason != NULL) { |
| 201 PrintF(" [%s]", current_.collector_reason); |
| 202 } |
| 203 |
| 204 PrintF(".\n"); |
| 205 } |
| 206 |
| 207 |
| 208 void GCTracer::PrintNVP() const { |
| 209 PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init()); |
| 210 |
| 211 double duration = current_.end_time - current_.start_time; |
| 212 double spent_in_mutator = current_.start_time - previous_.end_time; |
| 213 |
| 214 PrintF("pause=%.1f ", duration); |
| 215 PrintF("mutator=%.1f ", spent_in_mutator); |
| 216 PrintF("gc=%s ", current_.TypeName(true)); |
| 217 |
| 218 PrintF("external=%.1f ", current_.scopes[Scope::EXTERNAL]); |
| 219 PrintF("mark=%.1f ", current_.scopes[Scope::MC_MARK]); |
| 220 PrintF("sweep=%.2f ", current_.scopes[Scope::MC_SWEEP]); |
| 221 PrintF("sweepns=%.2f ", current_.scopes[Scope::MC_SWEEP_NEWSPACE]); |
| 222 PrintF("sweepos=%.2f ", current_.scopes[Scope::MC_SWEEP_OLDSPACE]); |
| 223 PrintF("sweepcode=%.2f ", current_.scopes[Scope::MC_SWEEP_CODE]); |
| 224 PrintF("sweepcell=%.2f ", current_.scopes[Scope::MC_SWEEP_CELL]); |
| 225 PrintF("sweepmap=%.2f ", current_.scopes[Scope::MC_SWEEP_MAP]); |
| 226 PrintF("evacuate=%.1f ", current_.scopes[Scope::MC_EVACUATE_PAGES]); |
| 227 PrintF("new_new=%.1f ", |
| 228 current_.scopes[Scope::MC_UPDATE_NEW_TO_NEW_POINTERS]); |
| 229 PrintF("root_new=%.1f ", |
| 230 current_.scopes[Scope::MC_UPDATE_ROOT_TO_NEW_POINTERS]); |
| 231 PrintF("old_new=%.1f ", |
| 232 current_.scopes[Scope::MC_UPDATE_OLD_TO_NEW_POINTERS]); |
| 233 PrintF("compaction_ptrs=%.1f ", |
| 234 current_.scopes[Scope::MC_UPDATE_POINTERS_TO_EVACUATED]); |
| 235 PrintF("intracompaction_ptrs=%.1f ", |
| 236 current_.scopes[Scope::MC_UPDATE_POINTERS_BETWEEN_EVACUATED]); |
| 237 PrintF("misc_compaction=%.1f ", |
| 238 current_.scopes[Scope::MC_UPDATE_MISC_POINTERS]); |
| 239 PrintF("weakcollection_process=%.1f ", |
| 240 current_.scopes[Scope::MC_WEAKCOLLECTION_PROCESS]); |
| 241 PrintF("weakcollection_clear=%.1f ", |
| 242 current_.scopes[Scope::MC_WEAKCOLLECTION_CLEAR]); |
| 243 |
| 244 PrintF("total_size_before=%" V8_PTR_PREFIX "d ", current_.start_object_size); |
| 245 PrintF("total_size_after=%" V8_PTR_PREFIX "d ", current_.end_object_size); |
| 246 PrintF("holes_size_before=%" V8_PTR_PREFIX "d ", current_.start_holes_size); |
| 247 PrintF("holes_size_after=%" V8_PTR_PREFIX "d ", current_.end_holes_size); |
| 248 |
| 249 intptr_t allocated_since_last_gc = |
| 250 current_.start_object_size - previous_.end_object_size; |
| 251 PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc); |
| 252 PrintF("promoted=%" V8_PTR_PREFIX "d ", heap_->promoted_objects_size_); |
| 253 PrintF("semi_space_copied=%" V8_PTR_PREFIX "d ", |
| 254 heap_->semi_space_copied_object_size_); |
| 255 PrintF("nodes_died_in_new=%d ", heap_->nodes_died_in_new_space_); |
| 256 PrintF("nodes_copied_in_new=%d ", heap_->nodes_copied_in_new_space_); |
| 257 PrintF("nodes_promoted=%d ", heap_->nodes_promoted_); |
| 258 PrintF("promotion_rate=%.1f%% ", heap_->promotion_rate_); |
| 259 PrintF("semi_space_copy_rate=%.1f%% ", heap_->semi_space_copied_rate_); |
| 260 |
| 261 if (current_.type == Event::SCAVENGER) { |
| 262 PrintF("stepscount=%d ", current_.incremental_marking_steps - |
| 263 previous_.incremental_marking_steps); |
| 264 PrintF("stepstook=%.1f ", current_.incremental_marking_duration - |
| 265 previous_.incremental_marking_duration); |
| 266 } else { |
| 267 PrintF("stepscount=%d ", current_.incremental_marking_steps - |
| 268 previous_mark_compactor_event_.incremental_marking_steps); |
| 269 PrintF("stepstook=%.1f ", current_.incremental_marking_duration - |
| 270 previous_mark_compactor_event_.incremental_marking_duration); |
| 271 PrintF("longeststep=%.1f ", current_.longest_incremental_marking_step); |
| 272 } |
| 273 |
| 274 PrintF("\n"); |
| 275 } |
| 276 |
| 277 } } // namespace v8::internal |
OLD | NEW |