V8 Project
gc-tracer.cc
Go to the documentation of this file.
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/heap/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(); space != NULL; space = spaces.next()) {
16  holes_size += space->Waste() + space->Available();
17  }
18  return holes_size;
19 }
20 
21 
23  intptr_t allocation_in_bytes) {
24  duration_ = duration;
25  allocation_in_bytes_ = allocation_in_bytes;
26 }
27 
28 
29 GCTracer::Event::Event(Type type, const char* gc_reason,
30  const char* collector_reason)
31  : type(type),
32  gc_reason(gc_reason),
33  collector_reason(collector_reason),
34  start_time(0.0),
35  end_time(0.0),
36  start_object_size(0),
37  end_object_size(0),
38  start_memory_size(0),
39  end_memory_size(0),
40  start_holes_size(0),
41  end_holes_size(0),
42  cumulative_incremental_marking_steps(0),
43  incremental_marking_steps(0),
44  cumulative_incremental_marking_bytes(0),
45  incremental_marking_bytes(0),
46  cumulative_incremental_marking_duration(0.0),
47  incremental_marking_duration(0.0),
48  cumulative_pure_incremental_marking_duration(0.0),
49  pure_incremental_marking_duration(0.0),
50  longest_incremental_marking_step(0.0) {
51  for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) {
52  scopes[i] = 0;
53  }
54 }
55 
56 
57 const char* GCTracer::Event::TypeName(bool short_name) const {
58  switch (type) {
59  case SCAVENGER:
60  if (short_name) {
61  return "s";
62  } else {
63  return "Scavenge";
64  }
65  case MARK_COMPACTOR:
66  if (short_name) {
67  return "ms";
68  } else {
69  return "Mark-sweep";
70  }
71  case START:
72  if (short_name) {
73  return "st";
74  } else {
75  return "Start";
76  }
77  }
78  return "Unknown Event Type";
79 }
80 
81 
83  : heap_(heap),
95 }
96 
97 
98 void GCTracer::Start(GarbageCollector collector, const char* gc_reason,
99  const char* collector_reason) {
101  double start_time = base::OS::TimeCurrentMillis();
102  if (new_space_top_after_gc_ != 0) {
104  start_time - previous_.end_time,
105  reinterpret_cast<intptr_t>((heap_->new_space()->top()) -
107  }
110 
111  if (collector == SCAVENGER) {
112  current_ = Event(Event::SCAVENGER, gc_reason, collector_reason);
113  } else {
114  current_ = Event(Event::MARK_COMPACTOR, gc_reason, collector_reason);
115  }
116 
117  current_.start_time = start_time;
122  heap_->new_space()->top() - heap_->new_space()->bottom();
123 
133 
134  for (int i = 0; i < Scope::NUMBER_OF_SCOPES; i++) {
135  current_.scopes[i] = 0;
136  }
137 }
138 
139 
146  reinterpret_cast<intptr_t>(heap_->new_space()->top());
147 
148  if (current_.type == Event::SCAVENGER) {
162  } else {
178  }
179 
180  // TODO(ernstm): move the code below out of GCTracer.
181 
182  if (!FLAG_trace_gc && !FLAG_print_cumulative_gc_stat) return;
183 
184  double duration = current_.end_time - current_.start_time;
185  double spent_in_mutator = Max(current_.start_time - previous_.end_time, 0.0);
186 
187  heap_->UpdateCumulativeGCStatistics(duration, spent_in_mutator,
189 
190  if (current_.type == Event::SCAVENGER && FLAG_trace_gc_ignore_scavenger)
191  return;
192 
193  if (FLAG_trace_gc) {
194  if (FLAG_trace_gc_nvp)
195  PrintNVP();
196  else
197  Print();
198 
200  }
201 }
202 
203 
205  intptr_t allocation_in_bytes) {
206  allocation_events_.push_front(AllocationEvent(duration, allocation_in_bytes));
207 }
208 
209 
210 void GCTracer::AddIncrementalMarkingStep(double duration, intptr_t bytes) {
216  cumulative_marking_duration_ += duration;
217  if (bytes > 0) {
219  }
220 }
221 
222 
223 void GCTracer::Print() const {
224  PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init());
225 
226  PrintF("%s %.1f (%.1f) -> %.1f (%.1f) MB, ", current_.TypeName(false),
227  static_cast<double>(current_.start_object_size) / MB,
228  static_cast<double>(current_.start_memory_size) / MB,
229  static_cast<double>(current_.end_object_size) / MB,
230  static_cast<double>(current_.end_memory_size) / MB);
231 
232  int external_time = static_cast<int>(current_.scopes[Scope::EXTERNAL]);
233  if (external_time > 0) PrintF("%d / ", external_time);
234 
235  double duration = current_.end_time - current_.start_time;
236  PrintF("%.1f ms", duration);
237  if (current_.type == Event::SCAVENGER) {
239  PrintF(" (+ %.1f ms in %d steps since last GC)",
242  }
243  } else {
245  PrintF(
246  " (+ %.1f ms in %d steps since start of marking, "
247  "biggest step %.1f ms)",
251  }
252  }
253 
254  if (current_.gc_reason != NULL) {
255  PrintF(" [%s]", current_.gc_reason);
256  }
257 
258  if (current_.collector_reason != NULL) {
259  PrintF(" [%s]", current_.collector_reason);
260  }
261 
262  PrintF(".\n");
263 }
264 
265 
266 void GCTracer::PrintNVP() const {
267  PrintPID("%8.0f ms: ", heap_->isolate()->time_millis_since_init());
268 
269  double duration = current_.end_time - current_.start_time;
270  double spent_in_mutator = current_.start_time - previous_.end_time;
271 
272  PrintF("pause=%.1f ", duration);
273  PrintF("mutator=%.1f ", spent_in_mutator);
274  PrintF("gc=%s ", current_.TypeName(true));
275 
276  PrintF("external=%.1f ", current_.scopes[Scope::EXTERNAL]);
277  PrintF("mark=%.1f ", current_.scopes[Scope::MC_MARK]);
278  PrintF("sweep=%.2f ", current_.scopes[Scope::MC_SWEEP]);
279  PrintF("sweepns=%.2f ", current_.scopes[Scope::MC_SWEEP_NEWSPACE]);
280  PrintF("sweepos=%.2f ", current_.scopes[Scope::MC_SWEEP_OLDSPACE]);
281  PrintF("sweepcode=%.2f ", current_.scopes[Scope::MC_SWEEP_CODE]);
282  PrintF("sweepcell=%.2f ", current_.scopes[Scope::MC_SWEEP_CELL]);
283  PrintF("sweepmap=%.2f ", current_.scopes[Scope::MC_SWEEP_MAP]);
284  PrintF("evacuate=%.1f ", current_.scopes[Scope::MC_EVACUATE_PAGES]);
285  PrintF("new_new=%.1f ",
287  PrintF("root_new=%.1f ",
289  PrintF("old_new=%.1f ",
291  PrintF("compaction_ptrs=%.1f ",
293  PrintF("intracompaction_ptrs=%.1f ",
295  PrintF("misc_compaction=%.1f ",
297  PrintF("weakcollection_process=%.1f ",
299  PrintF("weakcollection_clear=%.1f ",
301  PrintF("weakcollection_abort=%.1f ",
303 
304  PrintF("total_size_before=%" V8_PTR_PREFIX "d ", current_.start_object_size);
305  PrintF("total_size_after=%" V8_PTR_PREFIX "d ", current_.end_object_size);
306  PrintF("holes_size_before=%" V8_PTR_PREFIX "d ", current_.start_holes_size);
307  PrintF("holes_size_after=%" V8_PTR_PREFIX "d ", current_.end_holes_size);
308 
309  intptr_t allocated_since_last_gc =
311  PrintF("allocated=%" V8_PTR_PREFIX "d ", allocated_since_last_gc);
312  PrintF("promoted=%" V8_PTR_PREFIX "d ", heap_->promoted_objects_size_);
313  PrintF("semi_space_copied=%" V8_PTR_PREFIX "d ",
315  PrintF("nodes_died_in_new=%d ", heap_->nodes_died_in_new_space_);
316  PrintF("nodes_copied_in_new=%d ", heap_->nodes_copied_in_new_space_);
317  PrintF("nodes_promoted=%d ", heap_->nodes_promoted_);
318  PrintF("promotion_rate=%.1f%% ", heap_->promotion_rate_);
319  PrintF("semi_space_copy_rate=%.1f%% ", heap_->semi_space_copied_rate_);
320  PrintF("new_space_allocation_throughput=%" V8_PTR_PREFIX "d ",
322 
323  if (current_.type == Event::SCAVENGER) {
324  PrintF("steps_count=%d ", current_.incremental_marking_steps);
325  PrintF("steps_took=%.1f ", current_.incremental_marking_duration);
326  PrintF("scavenge_throughput=%" V8_PTR_PREFIX "d ",
328  } else {
329  PrintF("steps_count=%d ", current_.incremental_marking_steps);
330  PrintF("steps_took=%.1f ", current_.incremental_marking_duration);
331  PrintF("longest_step=%.1f ", current_.longest_incremental_marking_step);
332  PrintF("incremental_marking_throughput=%" V8_PTR_PREFIX "d ",
334  }
335 
336  PrintF("\n");
337 }
338 
339 
340 double GCTracer::MeanDuration(const EventBuffer& events) const {
341  if (events.empty()) return 0.0;
342 
343  double mean = 0.0;
344  EventBuffer::const_iterator iter = events.begin();
345  while (iter != events.end()) {
346  mean += iter->end_time - iter->start_time;
347  ++iter;
348  }
349 
350  return mean / events.size();
351 }
352 
353 
354 double GCTracer::MaxDuration(const EventBuffer& events) const {
355  if (events.empty()) return 0.0;
356 
357  double maximum = 0.0f;
358  EventBuffer::const_iterator iter = events.begin();
359  while (iter != events.end()) {
360  maximum = Max(iter->end_time - iter->start_time, maximum);
361  ++iter;
362  }
363 
364  return maximum;
365 }
366 
367 
369  if (cumulative_incremental_marking_steps_ == 0) return 0.0;
370 
371  // We haven't completed an entire round of incremental marking, yet.
372  // Use data from GCTracer instead of data from event buffers.
376  }
377 
378  int steps = 0;
379  double durations = 0.0;
380  EventBuffer::const_iterator iter = mark_compactor_events_.begin();
381  while (iter != mark_compactor_events_.end()) {
382  steps += iter->incremental_marking_steps;
383  durations += iter->incremental_marking_duration;
384  ++iter;
385  }
386 
387  if (steps == 0) return 0.0;
388 
389  return durations / steps;
390 }
391 
392 
394  // We haven't completed an entire round of incremental marking, yet.
395  // Use data from GCTracer instead of data from event buffers.
397 
398  double max_duration = 0.0;
399  EventBuffer::const_iterator iter = mark_compactor_events_.begin();
400  while (iter != mark_compactor_events_.end())
401  max_duration = Max(iter->longest_incremental_marking_step, max_duration);
402 
403  return max_duration;
404 }
405 
406 
408  if (cumulative_incremental_marking_duration_ == 0.0) return 0;
409 
410  // We haven't completed an entire round of incremental marking, yet.
411  // Use data from GCTracer instead of data from event buffers.
413  return static_cast<intptr_t>(cumulative_incremental_marking_bytes_ /
415  }
416 
417  intptr_t bytes = 0;
418  double durations = 0.0;
419  EventBuffer::const_iterator iter = mark_compactor_events_.begin();
420  while (iter != mark_compactor_events_.end()) {
421  bytes += iter->incremental_marking_bytes;
422  durations += iter->pure_incremental_marking_duration;
423  ++iter;
424  }
425 
426  if (durations == 0.0) return 0;
427 
428  return static_cast<intptr_t>(bytes / durations);
429 }
430 
431 
433  intptr_t bytes = 0;
434  double durations = 0.0;
435  EventBuffer::const_iterator iter = scavenger_events_.begin();
436  while (iter != scavenger_events_.end()) {
437  bytes += iter->new_space_object_size;
438  durations += iter->end_time - iter->start_time;
439  ++iter;
440  }
441 
442  if (durations == 0.0) return 0;
443 
444  return static_cast<intptr_t>(bytes / durations);
445 }
446 
447 
449  intptr_t bytes = 0;
450  double durations = 0.0;
451  EventBuffer::const_iterator iter = mark_compactor_events_.begin();
452  while (iter != mark_compactor_events_.end()) {
453  bytes += iter->start_object_size;
454  durations += iter->end_time - iter->start_time +
455  iter->pure_incremental_marking_duration;
456  ++iter;
457  }
458 
459  if (durations == 0.0) return 0;
460 
461  return static_cast<intptr_t>(bytes / durations);
462 }
463 
464 
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 }
479 }
480 } // namespace v8::internal
static double TimeCurrentMillis()
double cumulative_pure_incremental_marking_duration
Definition: gc-tracer.h:223
double cumulative_incremental_marking_duration
Definition: gc-tracer.h:214
const char * TypeName(bool short_name) const
Definition: gc-tracer.cc:57
intptr_t cumulative_incremental_marking_bytes
Definition: gc-tracer.h:205
double scopes[Scope::NUMBER_OF_SCOPES]
Definition: gc-tracer.h:235
void Print() const
Definition: gc-tracer.cc:223
double longest_incremental_marking_step_
Definition: gc-tracer.h:377
intptr_t MarkCompactSpeedInBytesPerMillisecond() const
Definition: gc-tracer.cc:448
int cumulative_incremental_marking_steps_
Definition: gc-tracer.h:363
double MaxDuration(const EventBuffer &events) const
Definition: gc-tracer.cc:354
void AddIncrementalMarkingStep(double duration, intptr_t bytes)
Definition: gc-tracer.cc:210
intptr_t IncrementalMarkingSpeedInBytesPerMillisecond() const
Definition: gc-tracer.cc:407
double MeanDuration(const EventBuffer &events) const
Definition: gc-tracer.cc:340
double cumulative_pure_incremental_marking_duration_
Definition: gc-tracer.h:374
GCTracer(Heap *heap)
Definition: gc-tracer.cc:82
double MaxIncrementalMarkingDuration() const
Definition: gc-tracer.cc:393
intptr_t ScavengeSpeedInBytesPerMillisecond() const
Definition: gc-tracer.cc:432
double cumulative_incremental_marking_duration_
Definition: gc-tracer.h:370
double MeanIncrementalMarkingDuration() const
Definition: gc-tracer.cc:368
Event previous_mark_compactor_event_
Definition: gc-tracer.h:351
void Start(GarbageCollector collector, const char *gc_reason, const char *collector_reason)
Definition: gc-tracer.cc:98
double cumulative_sweeping_duration_
Definition: gc-tracer.h:390
intptr_t NewSpaceAllocationThroughputInBytesPerMillisecond() const
Definition: gc-tracer.cc:465
void AddNewSpaceAllocationTime(double duration, intptr_t allocation_in_bytes)
Definition: gc-tracer.cc:204
intptr_t new_space_top_after_gc_
Definition: gc-tracer.h:394
AllocationEventBuffer allocation_events_
Definition: gc-tracer.h:360
void PrintNVP() const
Definition: gc-tracer.cc:266
EventBuffer mark_compactor_events_
Definition: gc-tracer.h:357
intptr_t cumulative_incremental_marking_bytes_
Definition: gc-tracer.h:367
EventBuffer scavenger_events_
Definition: gc-tracer.h:354
double cumulative_marking_duration_
Definition: gc-tracer.h:381
int nodes_copied_in_new_space_
Definition: heap.h:1914
void UpdateCumulativeGCStatistics(double duration, double spent_in_mutator, double marking_time)
Definition: heap.cc:5881
Isolate * isolate()
Definition: heap-inl.h:589
int nodes_died_in_new_space_
Definition: heap.h:1913
int nodes_promoted_
Definition: heap.h:1915
void PrintShortHeapStatistics()
Definition: heap.cc:313
NewSpace * new_space()
Definition: heap.h:593
double semi_space_copied_rate_
Definition: heap.h:1912
intptr_t promoted_objects_size_
Definition: heap.h:1909
double promotion_rate_
Definition: heap.h:1910
intptr_t SizeOfObjects()
Definition: heap.cc:460
intptr_t semi_space_copied_object_size_
Definition: heap.h:1911
double time_millis_since_init()
Definition: isolate.h:1016
MemoryAllocator * memory_allocator()
Definition: isolate.h:883
void push_front(const T &element)
Definition: gc-tracer.h:68
bool empty() const
Definition: gc-tracer.h:56
const_iterator begin() const
Definition: gc-tracer.h:60
size_t size() const
Definition: gc-tracer.h:57
const_iterator end() const
Definition: gc-tracer.h:61
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be expose gc extension under the specified name show built in functions in stack traces use random jit cookie to mask large constants minimum length for automatic enable preparsing CPU profiler sampling interval in microseconds trace out of bounds accesses to external arrays default size of stack region v8 is allowed to maximum length of function source code printed in a stack trace min size of a semi space(in MBytes)
enable harmony numeric enable harmony object literal extensions Optimize object Array DOM strings and string trace pretenuring decisions of HAllocate instructions Enables optimizations which favor memory size over execution speed maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining trace the tracking of allocation sites deoptimize every n garbage collections perform array bounds checks elimination analyze liveness of environment slots and zap dead values flushes the cache of optimized code for closures on every GC allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes enable context specialization in TurboFan execution budget before interrupt is triggered max percentage of megamorphic generic ICs to allow optimization enable use of SAHF instruction if enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable use of MLS instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long enable alignment of csp to bytes on platforms which prefer the register to always be NULL
#define V8_PTR_PREFIX
Definition: macros.h:360
void PrintPID(const char *format,...)
Definition: utils.cc:96
static intptr_t CountTotalHolesSize(Heap *heap)
Definition: gc-tracer.cc:12
static LifetimePosition Max(LifetimePosition a, LifetimePosition b)
void PrintF(const char *format,...)
Definition: utils.cc:80
const int MB
Definition: globals.h:107
@ MARK_COMPACTOR
Definition: globals.h:389
Debugger support for the V8 JavaScript engine.
Definition: accessors.cc:20