5 #ifndef V8_HEAP_GC_TRACER_H_ 6 #define V8_HEAP_GC_TRACER_H_ 8 #include "src/base/compiler-specific.h" 9 #include "src/base/platform/platform.h" 10 #include "src/base/ring-buffer.h" 11 #include "src/counters.h" 12 #include "src/globals.h" 13 #include "src/heap-symbols.h" 14 #include "src/heap/heap.h" 15 #include "testing/gtest/include/gtest/gtest_prod.h" 20 typedef std::pair<uint64_t, double> BytesAndDuration;
22 inline BytesAndDuration MakeBytesAndDuration(uint64_t bytes,
double duration) {
23 return std::make_pair(bytes, duration);
26 enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects };
28 #define TRACE_GC(tracer, scope_id) \ 29 GCTracer::Scope::ScopeId gc_tracer_scope_id(scope_id); \ 30 GCTracer::Scope gc_tracer_scope(tracer, gc_tracer_scope_id); \ 31 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.gc"), \ 32 GCTracer::Scope::Name(gc_tracer_scope_id)) 34 #define TRACE_BACKGROUND_GC(tracer, scope_id) \ 35 GCTracer::BackgroundScope background_scope(tracer, scope_id); \ 36 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.gc"), \ 37 GCTracer::BackgroundScope::Name(scope_id)) 46 void Update(
double duration) {
48 this->duration += duration;
49 if (duration > longest_step) {
50 longest_step = duration;
54 void ResetCurrentCycle() {
68 #define DEFINE_SCOPE(scope) scope, 69 TRACER_SCOPES(DEFINE_SCOPE) TRACER_BACKGROUND_SCOPES(DEFINE_SCOPE)
73 FIRST_INCREMENTAL_SCOPE = MC_INCREMENTAL,
74 LAST_INCREMENTAL_SCOPE = MC_INCREMENTAL_EXTERNAL_PROLOGUE,
75 FIRST_SCOPE = MC_INCREMENTAL,
76 NUMBER_OF_INCREMENTAL_SCOPES =
77 LAST_INCREMENTAL_SCOPE - FIRST_INCREMENTAL_SCOPE + 1,
78 FIRST_GENERAL_BACKGROUND_SCOPE = BACKGROUND_ARRAY_BUFFER_FREE,
79 LAST_GENERAL_BACKGROUND_SCOPE = BACKGROUND_UNMAPPER,
80 FIRST_MC_BACKGROUND_SCOPE = MC_BACKGROUND_EVACUATE_COPY,
81 LAST_MC_BACKGROUND_SCOPE = MC_BACKGROUND_SWEEPING,
82 FIRST_TOP_MC_SCOPE = MC_CLEAR,
83 LAST_TOP_MC_SCOPE = MC_SWEEP,
84 FIRST_MINOR_GC_BACKGROUND_SCOPE = MINOR_MC_BACKGROUND_EVACUATE_COPY,
85 LAST_MINOR_GC_BACKGROUND_SCOPE = SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL
90 static const char*
Name(ScopeId
id);
99 DISALLOW_COPY_AND_ASSIGN(
Scope);
105 #define DEFINE_SCOPE(scope) scope, 106 TRACER_BACKGROUND_SCOPES(DEFINE_SCOPE)
109 FIRST_GENERAL_BACKGROUND_SCOPE = BACKGROUND_ARRAY_BUFFER_FREE,
110 LAST_GENERAL_BACKGROUND_SCOPE = BACKGROUND_UNMAPPER,
111 FIRST_MC_BACKGROUND_SCOPE = MC_BACKGROUND_EVACUATE_COPY,
112 LAST_MC_BACKGROUND_SCOPE = MC_BACKGROUND_SWEEPING,
113 FIRST_MINOR_GC_BACKGROUND_SCOPE = MINOR_MC_BACKGROUND_EVACUATE_COPY,
114 LAST_MINOR_GC_BACKGROUND_SCOPE = SCAVENGER_BACKGROUND_SCAVENGE_PARALLEL
119 static const char*
Name(ScopeId
id);
127 bool runtime_stats_enabled_;
136 INCREMENTAL_MARK_COMPACTOR = 2,
137 MINOR_MARK_COMPACTOR = 3,
141 Event(Type
type, GarbageCollectionReason gc_reason,
142 const char* collector_reason);
145 const char* TypeName(
bool short_name)
const;
150 GarbageCollectionReason gc_reason;
151 const char* collector_reason;
163 size_t start_object_size;
166 size_t end_object_size;
169 size_t start_memory_size;
172 size_t end_memory_size;
176 size_t start_holes_size;
180 size_t end_holes_size;
183 size_t new_space_object_size;
186 size_t survived_new_space_object_size;
189 size_t incremental_marking_bytes;
192 double incremental_marking_duration;
195 double scopes[Scope::NUMBER_OF_SCOPES];
199 incremental_marking_scopes[Scope::NUMBER_OF_INCREMENTAL_SCOPES];
202 static const int kThroughputTimeFrameMs = 5000;
204 static RuntimeCallCounterId RCSCounterFromScope(Scope::ScopeId
id);
209 void Start(GarbageCollector collector, GarbageCollectionReason gc_reason,
210 const char* collector_reason);
213 void Stop(GarbageCollector collector);
215 void NotifyYoungGenerationHandling(
216 YoungGenerationHandling young_generation_handling);
219 void SampleAllocation(
double current_ms,
size_t new_space_counter_bytes,
220 size_t old_generation_counter_bytes);
223 void AddAllocation(
double current_ms);
225 void AddContextDisposalTime(
double time);
227 void AddCompactionEvent(
double duration,
size_t live_bytes_compacted);
229 void AddSurvivalRatio(
double survival_ratio);
232 void AddIncrementalMarkingStep(
double duration,
size_t bytes);
236 double IncrementalMarkingSpeedInBytesPerMillisecond()
const;
240 double ScavengeSpeedInBytesPerMillisecond(
241 ScavengeSpeedMode mode = kForAllObjects)
const;
245 double CompactionSpeedInBytesPerMillisecond()
const;
249 double MarkCompactSpeedInBytesPerMillisecond()
const;
254 double FinalIncrementalMarkCompactSpeedInBytesPerMillisecond()
const;
258 double CombinedMarkCompactSpeedInBytesPerMillisecond();
262 double NewSpaceAllocationThroughputInBytesPerMillisecond(
263 double time_ms = 0)
const;
268 double OldGenerationAllocationThroughputInBytesPerMillisecond(
269 double time_ms = 0)
const;
274 double AllocationThroughputInBytesPerMillisecond(
double time_ms)
const;
279 double CurrentAllocationThroughputInBytesPerMillisecond()
const;
284 double CurrentOldGenerationAllocationThroughputInBytesPerMillisecond()
const;
290 double ContextDisposalRateInMilliseconds()
const;
295 double AverageSurvivalRatio()
const;
298 bool SurvivalEventsRecorded()
const;
301 void ResetSurvivalEvents();
303 void NotifyIncrementalMarkingStart();
307 double AverageMarkCompactMutatorUtilization()
const;
308 double CurrentMarkCompactMutatorUtilization()
const;
310 V8_INLINE
void AddScopeSample(Scope::ScopeId scope,
double duration) {
311 DCHECK(scope < Scope::NUMBER_OF_SCOPES);
312 if (scope >= Scope::FIRST_INCREMENTAL_SCOPE &&
313 scope <= Scope::LAST_INCREMENTAL_SCOPE) {
314 incremental_marking_scopes_[scope - Scope::FIRST_INCREMENTAL_SCOPE]
317 current_.scopes[scope] += duration;
321 void AddBackgroundScopeSample(BackgroundScope::ScopeId scope,
double duration,
322 RuntimeCallCounter* runtime_call_counter);
324 void RecordGCPhasesHistograms(TimedHistogram* gc_timer);
327 FRIEND_TEST(GCTracer, AverageSpeed);
328 FRIEND_TEST(GCTracerTest, AllocationThroughput);
329 FRIEND_TEST(GCTracerTest, BackgroundScavengerScope);
330 FRIEND_TEST(GCTracerTest, BackgroundMinorMCScope);
331 FRIEND_TEST(GCTracerTest, BackgroundMajorMCScope);
332 FRIEND_TEST(GCTracerTest, MultithreadedBackgroundScope);
333 FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughput);
334 FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughputWithProvidedTime);
335 FRIEND_TEST(GCTracerTest, OldGenerationAllocationThroughputWithProvidedTime);
336 FRIEND_TEST(GCTracerTest, RegularScope);
337 FRIEND_TEST(GCTracerTest, IncrementalMarkingDetails);
338 FRIEND_TEST(GCTracerTest, IncrementalScope);
339 FRIEND_TEST(GCTracerTest, IncrementalMarkingSpeed);
340 FRIEND_TEST(GCTracerTest, MutatorUtilization);
341 FRIEND_TEST(GCTracerTest, RecordGCSumHistograms);
342 FRIEND_TEST(GCTracerTest, RecordMarkCompactHistograms);
343 FRIEND_TEST(GCTracerTest, RecordScavengerHistograms);
345 struct BackgroundCounter {
346 double total_duration_ms;
347 RuntimeCallCounter runtime_call_counter;
353 static double AverageSpeed(
const base::RingBuffer<BytesAndDuration>& buffer);
354 static double AverageSpeed(
const base::RingBuffer<BytesAndDuration>& buffer,
355 const BytesAndDuration& initial,
double time_ms);
357 void ResetForTesting();
358 void ResetIncrementalMarkingCounters();
359 void RecordIncrementalMarkingSpeed(
size_t bytes,
double duration);
360 void RecordMutatorUtilization(
double mark_compactor_end_time,
361 double mark_compactor_duration);
366 void RecordGCSumCounters(
double atomic_pause_duration);
370 void PrintNVP()
const;
378 void PRINTF_FORMAT(2, 3) Output(const
char* format, ...) const;
380 double TotalExternalTime()
const {
381 return current_.scopes[Scope::HEAP_EXTERNAL_WEAK_GLOBAL_HANDLES] +
382 current_.scopes[Scope::HEAP_EXTERNAL_EPILOGUE] +
383 current_.scopes[Scope::HEAP_EXTERNAL_PROLOGUE] +
384 current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_EPILOGUE] +
385 current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE];
388 void FetchBackgroundCounters(
int first_global_scope,
int last_global_scope,
389 int first_background_scope,
390 int last_background_scope);
391 void FetchBackgroundMinorGCCounters();
392 void FetchBackgroundMarkCompactCounters();
393 void FetchBackgroundGeneralCounters();
407 size_t incremental_marking_bytes_;
411 double incremental_marking_duration_;
413 double incremental_marking_start_time_;
415 double recorded_incremental_marking_speed_;
419 IncrementalMarkingInfos
420 incremental_marking_scopes_[Scope::NUMBER_OF_INCREMENTAL_SCOPES];
424 double allocation_time_ms_;
425 size_t new_space_allocation_counter_bytes_;
426 size_t old_generation_allocation_counter_bytes_;
429 double allocation_duration_since_gc_;
430 size_t new_space_allocation_in_bytes_since_gc_;
431 size_t old_generation_allocation_in_bytes_since_gc_;
433 double combined_mark_compact_speed_cache_;
439 double average_mutator_duration_;
440 double average_mark_compact_duration_;
441 double current_mark_compact_mutator_utilization_;
442 double previous_mark_compact_end_time_;
444 base::RingBuffer<BytesAndDuration> recorded_minor_gcs_total_;
445 base::RingBuffer<BytesAndDuration> recorded_minor_gcs_survived_;
446 base::RingBuffer<BytesAndDuration> recorded_compactions_;
447 base::RingBuffer<BytesAndDuration> recorded_incremental_mark_compacts_;
448 base::RingBuffer<BytesAndDuration> recorded_mark_compacts_;
449 base::RingBuffer<BytesAndDuration> recorded_new_generation_allocations_;
450 base::RingBuffer<BytesAndDuration> recorded_old_generation_allocations_;
451 base::RingBuffer<double> recorded_context_disposal_times_;
452 base::RingBuffer<double> recorded_survival_ratios_;
454 base::Mutex background_counter_mutex_;
455 BackgroundCounter background_counter_[BackgroundScope::NUMBER_OF_SCOPES];
457 DISALLOW_COPY_AND_ASSIGN(GCTracer);
463 #endif // V8_HEAP_GC_TRACER_H_