LCOV - code coverage report
Current view: top level - src/heap - gc-tracer.h (source / functions) Hit Total Coverage
Test: app.info Lines: 19 19 100.0 %
Date: 2017-04-26 Functions: 1 1 100.0 %

          Line data    Source code
       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             : #ifndef V8_HEAP_GC_TRACER_H_
       6             : #define V8_HEAP_GC_TRACER_H_
       7             : 
       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 "testing/gtest/include/gtest/gtest_prod.h"  // nogncheck
      14             : 
      15             : namespace v8 {
      16             : namespace internal {
      17             : 
      18             : typedef std::pair<uint64_t, double> BytesAndDuration;
      19             : 
      20             : inline BytesAndDuration MakeBytesAndDuration(uint64_t bytes, double duration) {
      21             :   return std::make_pair(bytes, duration);
      22             : }
      23             : 
      24             : enum ScavengeSpeedMode { kForAllObjects, kForSurvivedObjects };
      25             : 
      26             : #define INCREMENTAL_SCOPES(F)                                      \
      27             :   /* MC_INCREMENTAL is the top-level incremental marking scope. */ \
      28             :   F(MC_INCREMENTAL)                                                \
      29             :   F(MC_INCREMENTAL_SWEEPING)                                       \
      30             :   F(MC_INCREMENTAL_WRAPPER_PROLOGUE)                               \
      31             :   F(MC_INCREMENTAL_WRAPPER_TRACING)                                \
      32             :   F(MC_INCREMENTAL_FINALIZE)                                       \
      33             :   F(MC_INCREMENTAL_FINALIZE_BODY)                                  \
      34             :   F(MC_INCREMENTAL_EXTERNAL_EPILOGUE)                              \
      35             :   F(MC_INCREMENTAL_EXTERNAL_PROLOGUE)
      36             : 
      37             : #define TRACER_SCOPES(F)                      \
      38             :   INCREMENTAL_SCOPES(F)                       \
      39             :   F(HEAP_EPILOGUE)                            \
      40             :   F(HEAP_EPILOGUE_REDUCE_NEW_SPACE)           \
      41             :   F(HEAP_EXTERNAL_EPILOGUE)                   \
      42             :   F(HEAP_EXTERNAL_PROLOGUE)                   \
      43             :   F(HEAP_EXTERNAL_WEAK_GLOBAL_HANDLES)        \
      44             :   F(HEAP_PROLOGUE)                            \
      45             :   F(MC_CLEAR)                                 \
      46             :   F(MC_CLEAR_CODE_FLUSH)                      \
      47             :   F(MC_CLEAR_DEPENDENT_CODE)                  \
      48             :   F(MC_CLEAR_MAPS)                            \
      49             :   F(MC_CLEAR_SLOTS_BUFFER)                    \
      50             :   F(MC_CLEAR_STORE_BUFFER)                    \
      51             :   F(MC_CLEAR_STRING_TABLE)                    \
      52             :   F(MC_CLEAR_WEAK_CELLS)                      \
      53             :   F(MC_CLEAR_WEAK_COLLECTIONS)                \
      54             :   F(MC_CLEAR_WEAK_LISTS)                      \
      55             :   F(MC_EPILOGUE)                              \
      56             :   F(MC_EVACUATE)                              \
      57             :   F(MC_EVACUATE_CANDIDATES)                   \
      58             :   F(MC_EVACUATE_CLEAN_UP)                     \
      59             :   F(MC_EVACUATE_COPY)                         \
      60             :   F(MC_EVACUATE_EPILOGUE)                     \
      61             :   F(MC_EVACUATE_PROLOGUE)                     \
      62             :   F(MC_EVACUATE_REBALANCE)                    \
      63             :   F(MC_EVACUATE_UPDATE_POINTERS)              \
      64             :   F(MC_EVACUATE_UPDATE_POINTERS_TO_EVACUATED) \
      65             :   F(MC_EVACUATE_UPDATE_POINTERS_TO_NEW)       \
      66             :   F(MC_EVACUATE_UPDATE_POINTERS_WEAK)         \
      67             :   F(MC_FINISH)                                \
      68             :   F(MC_MARK)                                  \
      69             :   F(MC_MARK_FINISH_INCREMENTAL)               \
      70             :   F(MC_MARK_PREPARE_CODE_FLUSH)               \
      71             :   F(MC_MARK_ROOTS)                            \
      72             :   F(MC_MARK_WEAK_CLOSURE)                     \
      73             :   F(MC_MARK_WEAK_CLOSURE_EPHEMERAL)           \
      74             :   F(MC_MARK_WEAK_CLOSURE_WEAK_HANDLES)        \
      75             :   F(MC_MARK_WEAK_CLOSURE_WEAK_ROOTS)          \
      76             :   F(MC_MARK_WEAK_CLOSURE_HARMONY)             \
      77             :   F(MC_MARK_WRAPPER_EPILOGUE)                 \
      78             :   F(MC_MARK_WRAPPER_PROLOGUE)                 \
      79             :   F(MC_MARK_WRAPPER_TRACING)                  \
      80             :   F(MC_PROLOGUE)                              \
      81             :   F(MC_SWEEP)                                 \
      82             :   F(MC_SWEEP_CODE)                            \
      83             :   F(MC_SWEEP_MAP)                             \
      84             :   F(MC_SWEEP_OLD)                             \
      85             :   F(MC_MINOR_MC)                              \
      86             :   F(MINOR_MC_MARK)                            \
      87             :   F(MINOR_MC_MARK_CODE_FLUSH_CANDIDATES)      \
      88             :   F(MINOR_MC_MARK_GLOBAL_HANDLES)             \
      89             :   F(MINOR_MC_MARK_OLD_TO_NEW_POINTERS)        \
      90             :   F(MINOR_MC_MARK_ROOTS)                      \
      91             :   F(MINOR_MC_MARK_WEAK)                       \
      92             :   F(SCAVENGER_CODE_FLUSH_CANDIDATES)          \
      93             :   F(SCAVENGER_EVACUATE)                       \
      94             :   F(SCAVENGER_OLD_TO_NEW_POINTERS)            \
      95             :   F(SCAVENGER_ROOTS)                          \
      96             :   F(SCAVENGER_SCAVENGE)                       \
      97             :   F(SCAVENGER_SEMISPACE)                      \
      98             :   F(SCAVENGER_WEAK)
      99             : 
     100             : #define TRACE_GC(tracer, scope_id)                             \
     101             :   GCTracer::Scope::ScopeId gc_tracer_scope_id(scope_id);       \
     102             :   GCTracer::Scope gc_tracer_scope(tracer, gc_tracer_scope_id); \
     103             :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.gc"),             \
     104             :                GCTracer::Scope::Name(gc_tracer_scope_id))
     105             : 
     106             : // GCTracer collects and prints ONE line after each garbage collector
     107             : // invocation IFF --trace_gc is used.
     108             : class V8_EXPORT_PRIVATE GCTracer {
     109             :  public:
     110             :   struct IncrementalMarkingInfos {
     111     1952632 :     IncrementalMarkingInfos() : duration(0), longest_step(0), steps(0) {}
     112             : 
     113       25363 :     void Update(double duration) {
     114       25363 :       steps++;
     115       25363 :       this->duration += duration;
     116       25363 :       if (duration > longest_step) {
     117        6187 :         longest_step = duration;
     118             :       }
     119       25363 :     }
     120             : 
     121             :     void ResetCurrentCycle() {
     122      426784 :       duration = 0;
     123      426784 :       longest_step = 0;
     124      426784 :       steps = 0;
     125             :     }
     126             : 
     127             :     double duration;
     128             :     double longest_step;
     129             :     int steps;
     130             :   };
     131             : 
     132             :   class Scope {
     133             :    public:
     134             :     enum ScopeId {
     135             : #define DEFINE_SCOPE(scope) scope,
     136             :       TRACER_SCOPES(DEFINE_SCOPE)
     137             : #undef DEFINE_SCOPE
     138             :           NUMBER_OF_SCOPES,
     139             : 
     140             :       FIRST_INCREMENTAL_SCOPE = MC_INCREMENTAL,
     141             :       LAST_INCREMENTAL_SCOPE = MC_INCREMENTAL_EXTERNAL_PROLOGUE,
     142             :       NUMBER_OF_INCREMENTAL_SCOPES =
     143             :           LAST_INCREMENTAL_SCOPE - FIRST_INCREMENTAL_SCOPE + 1
     144             :     };
     145             : 
     146             :     Scope(GCTracer* tracer, ScopeId scope);
     147             :     ~Scope();
     148             :     static const char* Name(ScopeId id);
     149             : 
     150             :    private:
     151             :     GCTracer* tracer_;
     152             :     ScopeId scope_;
     153             :     double start_time_;
     154             :     RuntimeCallTimer timer_;
     155             : 
     156             :     DISALLOW_COPY_AND_ASSIGN(Scope);
     157             :   };
     158             : 
     159             : 
     160             :   class Event {
     161             :    public:
     162             :     enum Type {
     163             :       SCAVENGER = 0,
     164             :       MARK_COMPACTOR = 1,
     165             :       INCREMENTAL_MARK_COMPACTOR = 2,
     166             :       MINOR_MARK_COMPACTOR = 3,
     167             :       START = 4
     168             :     };
     169             : 
     170             :     Event(Type type, GarbageCollectionReason gc_reason,
     171             :           const char* collector_reason);
     172             : 
     173             :     // Returns a string describing the event type.
     174             :     const char* TypeName(bool short_name) const;
     175             : 
     176             :     // Type of event
     177             :     Type type;
     178             : 
     179             :     GarbageCollectionReason gc_reason;
     180             :     const char* collector_reason;
     181             : 
     182             :     // Timestamp set in the constructor.
     183             :     double start_time;
     184             : 
     185             :     // Timestamp set in the destructor.
     186             :     double end_time;
     187             : 
     188             :     // Memory reduction flag set.
     189             :     bool reduce_memory;
     190             : 
     191             :     // Size of objects in heap set in constructor.
     192             :     size_t start_object_size;
     193             : 
     194             :     // Size of objects in heap set in destructor.
     195             :     size_t end_object_size;
     196             : 
     197             :     // Size of memory allocated from OS set in constructor.
     198             :     size_t start_memory_size;
     199             : 
     200             :     // Size of memory allocated from OS set in destructor.
     201             :     size_t end_memory_size;
     202             : 
     203             :     // Total amount of space either wasted or contained in one of free lists
     204             :     // before the current GC.
     205             :     size_t start_holes_size;
     206             : 
     207             :     // Total amount of space either wasted or contained in one of free lists
     208             :     // after the current GC.
     209             :     size_t end_holes_size;
     210             : 
     211             :     // Size of new space objects in constructor.
     212             :     size_t new_space_object_size;
     213             : 
     214             :     // Size of survived new space objects in destructor.
     215             :     size_t survived_new_space_object_size;
     216             : 
     217             :     // Bytes marked incrementally for INCREMENTAL_MARK_COMPACTOR
     218             :     size_t incremental_marking_bytes;
     219             : 
     220             :     // Duration of incremental marking steps for INCREMENTAL_MARK_COMPACTOR.
     221             :     double incremental_marking_duration;
     222             : 
     223             :     // Amounts of time spent in different scopes during GC.
     224             :     double scopes[Scope::NUMBER_OF_SCOPES];
     225             : 
     226             :     // Holds details for incremental marking scopes.
     227             :     IncrementalMarkingInfos
     228             :         incremental_marking_scopes[Scope::NUMBER_OF_INCREMENTAL_SCOPES];
     229             :   };
     230             : 
     231             :   static const int kThroughputTimeFrameMs = 5000;
     232             : 
     233             :   explicit GCTracer(Heap* heap);
     234             : 
     235             :   // Start collecting data.
     236             :   void Start(GarbageCollector collector, GarbageCollectionReason gc_reason,
     237             :              const char* collector_reason);
     238             : 
     239             :   // Stop collecting data and print results.
     240             :   void Stop(GarbageCollector collector);
     241             : 
     242             :   void NotifyYoungGenerationHandling(
     243             :       YoungGenerationHandling young_generation_handling);
     244             : 
     245             :   // Sample and accumulate bytes allocated since the last GC.
     246             :   void SampleAllocation(double current_ms, size_t new_space_counter_bytes,
     247             :                         size_t old_generation_counter_bytes);
     248             : 
     249             :   // Log the accumulated new space allocation bytes.
     250             :   void AddAllocation(double current_ms);
     251             : 
     252             :   void AddContextDisposalTime(double time);
     253             : 
     254             :   void AddCompactionEvent(double duration, size_t live_bytes_compacted);
     255             : 
     256             :   void AddSurvivalRatio(double survival_ratio);
     257             : 
     258             :   // Log an incremental marking step.
     259             :   void AddIncrementalMarkingStep(double duration, size_t bytes);
     260             : 
     261             :   // Compute the average incremental marking speed in bytes/millisecond.
     262             :   // Returns 0 if no events have been recorded.
     263             :   double IncrementalMarkingSpeedInBytesPerMillisecond() const;
     264             : 
     265             :   // Compute the average scavenge speed in bytes/millisecond.
     266             :   // Returns 0 if no events have been recorded.
     267             :   double ScavengeSpeedInBytesPerMillisecond(
     268             :       ScavengeSpeedMode mode = kForAllObjects) const;
     269             : 
     270             :   // Compute the average compaction speed in bytes/millisecond.
     271             :   // Returns 0 if not enough events have been recorded.
     272             :   double CompactionSpeedInBytesPerMillisecond() const;
     273             : 
     274             :   // Compute the average mark-sweep speed in bytes/millisecond.
     275             :   // Returns 0 if no events have been recorded.
     276             :   double MarkCompactSpeedInBytesPerMillisecond() const;
     277             : 
     278             :   // Compute the average incremental mark-sweep finalize speed in
     279             :   // bytes/millisecond.
     280             :   // Returns 0 if no events have been recorded.
     281             :   double FinalIncrementalMarkCompactSpeedInBytesPerMillisecond() const;
     282             : 
     283             :   // Compute the overall mark compact speed including incremental steps
     284             :   // and the final mark-compact step.
     285             :   double CombinedMarkCompactSpeedInBytesPerMillisecond();
     286             : 
     287             :   // Allocation throughput in the new space in bytes/millisecond.
     288             :   // Returns 0 if no allocation events have been recorded.
     289             :   double NewSpaceAllocationThroughputInBytesPerMillisecond(
     290             :       double time_ms = 0) const;
     291             : 
     292             :   // Allocation throughput in the old generation in bytes/millisecond in the
     293             :   // last time_ms milliseconds.
     294             :   // Returns 0 if no allocation events have been recorded.
     295             :   double OldGenerationAllocationThroughputInBytesPerMillisecond(
     296             :       double time_ms = 0) const;
     297             : 
     298             :   // Allocation throughput in heap in bytes/millisecond in the last time_ms
     299             :   // milliseconds.
     300             :   // Returns 0 if no allocation events have been recorded.
     301             :   double AllocationThroughputInBytesPerMillisecond(double time_ms) const;
     302             : 
     303             :   // Allocation throughput in heap in bytes/milliseconds in the last
     304             :   // kThroughputTimeFrameMs seconds.
     305             :   // Returns 0 if no allocation events have been recorded.
     306             :   double CurrentAllocationThroughputInBytesPerMillisecond() const;
     307             : 
     308             :   // Allocation throughput in old generation in bytes/milliseconds in the last
     309             :   // kThroughputTimeFrameMs seconds.
     310             :   // Returns 0 if no allocation events have been recorded.
     311             :   double CurrentOldGenerationAllocationThroughputInBytesPerMillisecond() const;
     312             : 
     313             :   // Computes the context disposal rate in milliseconds. It takes the time
     314             :   // frame of the first recorded context disposal to the current time and
     315             :   // divides it by the number of recorded events.
     316             :   // Returns 0 if no events have been recorded.
     317             :   double ContextDisposalRateInMilliseconds() const;
     318             : 
     319             :   // Computes the average survival ratio based on the last recorded survival
     320             :   // events.
     321             :   // Returns 0 if no events have been recorded.
     322             :   double AverageSurvivalRatio() const;
     323             : 
     324             :   // Returns true if at least one survival event was recorded.
     325             :   bool SurvivalEventsRecorded() const;
     326             : 
     327             :   // Discard all recorded survival events.
     328             :   void ResetSurvivalEvents();
     329             : 
     330             :   void NotifyIncrementalMarkingStart();
     331             : 
     332             :   V8_INLINE void AddScopeSample(Scope::ScopeId scope, double duration) {
     333             :     DCHECK(scope < Scope::NUMBER_OF_SCOPES);
     334     3094966 :     if (scope >= Scope::FIRST_INCREMENTAL_SCOPE &&
     335             :         scope <= Scope::LAST_INCREMENTAL_SCOPE) {
     336       25363 :       incremental_marking_scopes_[scope - Scope::FIRST_INCREMENTAL_SCOPE]
     337       25363 :           .Update(duration);
     338             :     } else {
     339     3069603 :       current_.scopes[scope] += duration;
     340             :     }
     341             :   }
     342             : 
     343             :  private:
     344             :   FRIEND_TEST(GCTracer, AverageSpeed);
     345             :   FRIEND_TEST(GCTracerTest, AllocationThroughput);
     346             :   FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughput);
     347             :   FRIEND_TEST(GCTracerTest, NewSpaceAllocationThroughputWithProvidedTime);
     348             :   FRIEND_TEST(GCTracerTest, OldGenerationAllocationThroughputWithProvidedTime);
     349             :   FRIEND_TEST(GCTracerTest, RegularScope);
     350             :   FRIEND_TEST(GCTracerTest, IncrementalMarkingDetails);
     351             :   FRIEND_TEST(GCTracerTest, IncrementalScope);
     352             :   FRIEND_TEST(GCTracerTest, IncrementalMarkingSpeed);
     353             : 
     354             :   // Returns the average speed of the events in the buffer.
     355             :   // If the buffer is empty, the result is 0.
     356             :   // Otherwise, the result is between 1 byte/ms and 1 GB/ms.
     357             :   static double AverageSpeed(const base::RingBuffer<BytesAndDuration>& buffer);
     358             :   static double AverageSpeed(const base::RingBuffer<BytesAndDuration>& buffer,
     359             :                              const BytesAndDuration& initial, double time_ms);
     360             : 
     361             :   void ResetForTesting();
     362             :   void ResetIncrementalMarkingCounters();
     363             :   void RecordIncrementalMarkingSpeed(size_t bytes, double duration);
     364             : 
     365             :   // Print one detailed trace line in name=value format.
     366             :   // TODO(ernstm): Move to Heap.
     367             :   void PrintNVP() const;
     368             : 
     369             :   // Print one trace line.
     370             :   // TODO(ernstm): Move to Heap.
     371             :   void Print() const;
     372             : 
     373             :   // Prints a line and also adds it to the heap's ring buffer so that
     374             :   // it can be included in later crash dumps.
     375             :   void PRINTF_FORMAT(2, 3) Output(const char* format, ...) const;
     376             : 
     377             :   double TotalExternalTime() const {
     378      245014 :     return current_.scopes[Scope::HEAP_EXTERNAL_WEAK_GLOBAL_HANDLES] +
     379      245014 :            current_.scopes[Scope::HEAP_EXTERNAL_EPILOGUE] +
     380      245014 :            current_.scopes[Scope::HEAP_EXTERNAL_PROLOGUE] +
     381      122507 :            current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_EPILOGUE] +
     382      122507 :            current_.scopes[Scope::MC_INCREMENTAL_EXTERNAL_PROLOGUE];
     383             :   }
     384             : 
     385             :   // Pointer to the heap that owns this tracer.
     386             :   Heap* heap_;
     387             : 
     388             :   // Current tracer event. Populated during Start/Stop cycle. Valid after Stop()
     389             :   // has returned.
     390             :   Event current_;
     391             : 
     392             :   // Previous tracer event.
     393             :   Event previous_;
     394             : 
     395             :   // Size of incremental marking steps (in bytes) accumulated since the end of
     396             :   // the last mark compact GC.
     397             :   size_t incremental_marking_bytes_;
     398             : 
     399             :   // Duration of incremental marking steps since the end of the last mark-
     400             :   // compact event.
     401             :   double incremental_marking_duration_;
     402             : 
     403             :   double incremental_marking_start_time_;
     404             : 
     405             :   double recorded_incremental_marking_speed_;
     406             : 
     407             :   // Incremental scopes carry more information than just the duration. The infos
     408             :   // here are merged back upon starting/stopping the GC tracer.
     409             :   IncrementalMarkingInfos
     410             :       incremental_marking_scopes_[Scope::NUMBER_OF_INCREMENTAL_SCOPES];
     411             : 
     412             : 
     413             :   // Timestamp and allocation counter at the last sampled allocation event.
     414             :   double allocation_time_ms_;
     415             :   size_t new_space_allocation_counter_bytes_;
     416             :   size_t old_generation_allocation_counter_bytes_;
     417             : 
     418             :   // Accumulated duration and allocated bytes since the last GC.
     419             :   double allocation_duration_since_gc_;
     420             :   size_t new_space_allocation_in_bytes_since_gc_;
     421             :   size_t old_generation_allocation_in_bytes_since_gc_;
     422             : 
     423             :   double combined_mark_compact_speed_cache_;
     424             : 
     425             :   // Counts how many tracers were started without stopping.
     426             :   int start_counter_;
     427             : 
     428             :   // Separate timer used for --runtime_call_stats
     429             :   RuntimeCallTimer timer_;
     430             : 
     431             :   base::RingBuffer<BytesAndDuration> recorded_minor_gcs_total_;
     432             :   base::RingBuffer<BytesAndDuration> recorded_minor_gcs_survived_;
     433             :   base::RingBuffer<BytesAndDuration> recorded_compactions_;
     434             :   base::RingBuffer<BytesAndDuration> recorded_incremental_mark_compacts_;
     435             :   base::RingBuffer<BytesAndDuration> recorded_mark_compacts_;
     436             :   base::RingBuffer<BytesAndDuration> recorded_new_generation_allocations_;
     437             :   base::RingBuffer<BytesAndDuration> recorded_old_generation_allocations_;
     438             :   base::RingBuffer<double> recorded_context_disposal_times_;
     439             :   base::RingBuffer<double> recorded_survival_ratios_;
     440             : 
     441             :   DISALLOW_COPY_AND_ASSIGN(GCTracer);
     442             : };
     443             : }  // namespace internal
     444             : }  // namespace v8
     445             : 
     446             : #endif  // V8_HEAP_GC_TRACER_H_

Generated by: LCOV version 1.10