| 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 #ifndef V8_GC_TRACER_H_ |  | 
|    6 #define V8_GC_TRACER_H_ |  | 
|    7  |  | 
|    8 namespace v8 { |  | 
|    9 namespace internal { |  | 
|   10  |  | 
|   11 // A simple ring buffer class with maximum size known at compile time. |  | 
|   12 // The class only implements the functionality required in GCTracer. |  | 
|   13 template <typename T, size_t MAX_SIZE> |  | 
|   14 class RingBuffer { |  | 
|   15  public: |  | 
|   16   class const_iterator { |  | 
|   17    public: |  | 
|   18     const_iterator() : index_(0), elements_(NULL) {} |  | 
|   19  |  | 
|   20     const_iterator(size_t index, const T* elements) |  | 
|   21         : index_(index), elements_(elements) {} |  | 
|   22  |  | 
|   23     bool operator==(const const_iterator& rhs) const { |  | 
|   24       return elements_ == rhs.elements_ && index_ == rhs.index_; |  | 
|   25     } |  | 
|   26  |  | 
|   27     bool operator!=(const const_iterator& rhs) const { |  | 
|   28       return elements_ != rhs.elements_ || index_ != rhs.index_; |  | 
|   29     } |  | 
|   30  |  | 
|   31     operator const T*() const { return elements_ + index_; } |  | 
|   32  |  | 
|   33     const T* operator->() const { return elements_ + index_; } |  | 
|   34  |  | 
|   35     const T& operator*() const { return elements_[index_]; } |  | 
|   36  |  | 
|   37     const_iterator& operator++() { |  | 
|   38       index_ = (index_ + 1) % (MAX_SIZE + 1); |  | 
|   39       return *this; |  | 
|   40     } |  | 
|   41  |  | 
|   42     const_iterator& operator--() { |  | 
|   43       index_ = (index_ + MAX_SIZE) % (MAX_SIZE + 1); |  | 
|   44       return *this; |  | 
|   45     } |  | 
|   46  |  | 
|   47    private: |  | 
|   48     size_t index_; |  | 
|   49     const T* elements_; |  | 
|   50   }; |  | 
|   51  |  | 
|   52   RingBuffer() : begin_(0), end_(0) {} |  | 
|   53  |  | 
|   54   bool empty() const { return begin_ == end_; } |  | 
|   55   size_t size() const { |  | 
|   56     return (end_ - begin_ + MAX_SIZE + 1) % (MAX_SIZE + 1); |  | 
|   57   } |  | 
|   58   const_iterator begin() const { return const_iterator(begin_, elements_); } |  | 
|   59   const_iterator end() const { return const_iterator(end_, elements_); } |  | 
|   60   const_iterator back() const { return --end(); } |  | 
|   61   void push_back(const T& element) { |  | 
|   62     elements_[end_] = element; |  | 
|   63     end_ = (end_ + 1) % (MAX_SIZE + 1); |  | 
|   64     if (end_ == begin_) begin_ = (begin_ + 1) % (MAX_SIZE + 1); |  | 
|   65   } |  | 
|   66   void push_front(const T& element) { |  | 
|   67     begin_ = (begin_ + MAX_SIZE) % (MAX_SIZE + 1); |  | 
|   68     if (begin_ == end_) end_ = (end_ + MAX_SIZE) % (MAX_SIZE + 1); |  | 
|   69     elements_[begin_] = element; |  | 
|   70   } |  | 
|   71  |  | 
|   72  private: |  | 
|   73   T elements_[MAX_SIZE + 1]; |  | 
|   74   size_t begin_; |  | 
|   75   size_t end_; |  | 
|   76  |  | 
|   77   DISALLOW_COPY_AND_ASSIGN(RingBuffer); |  | 
|   78 }; |  | 
|   79  |  | 
|   80  |  | 
|   81 // GCTracer collects and prints ONE line after each garbage collector |  | 
|   82 // invocation IFF --trace_gc is used. |  | 
|   83 // TODO(ernstm): Unit tests. |  | 
|   84 class GCTracer BASE_EMBEDDED { |  | 
|   85  public: |  | 
|   86   class Scope BASE_EMBEDDED { |  | 
|   87    public: |  | 
|   88     enum ScopeId { |  | 
|   89       EXTERNAL, |  | 
|   90       MC_MARK, |  | 
|   91       MC_SWEEP, |  | 
|   92       MC_SWEEP_NEWSPACE, |  | 
|   93       MC_SWEEP_OLDSPACE, |  | 
|   94       MC_SWEEP_CODE, |  | 
|   95       MC_SWEEP_CELL, |  | 
|   96       MC_SWEEP_MAP, |  | 
|   97       MC_EVACUATE_PAGES, |  | 
|   98       MC_UPDATE_NEW_TO_NEW_POINTERS, |  | 
|   99       MC_UPDATE_ROOT_TO_NEW_POINTERS, |  | 
|  100       MC_UPDATE_OLD_TO_NEW_POINTERS, |  | 
|  101       MC_UPDATE_POINTERS_TO_EVACUATED, |  | 
|  102       MC_UPDATE_POINTERS_BETWEEN_EVACUATED, |  | 
|  103       MC_UPDATE_MISC_POINTERS, |  | 
|  104       MC_WEAKCOLLECTION_PROCESS, |  | 
|  105       MC_WEAKCOLLECTION_CLEAR, |  | 
|  106       MC_FLUSH_CODE, |  | 
|  107       NUMBER_OF_SCOPES |  | 
|  108     }; |  | 
|  109  |  | 
|  110     Scope(GCTracer* tracer, ScopeId scope) : tracer_(tracer), scope_(scope) { |  | 
|  111       start_time_ = base::OS::TimeCurrentMillis(); |  | 
|  112     } |  | 
|  113  |  | 
|  114     ~Scope() { |  | 
|  115       DCHECK(scope_ < NUMBER_OF_SCOPES);  // scope_ is unsigned. |  | 
|  116       tracer_->current_.scopes[scope_] += |  | 
|  117           base::OS::TimeCurrentMillis() - start_time_; |  | 
|  118     } |  | 
|  119  |  | 
|  120    private: |  | 
|  121     GCTracer* tracer_; |  | 
|  122     ScopeId scope_; |  | 
|  123     double start_time_; |  | 
|  124  |  | 
|  125     DISALLOW_COPY_AND_ASSIGN(Scope); |  | 
|  126   }; |  | 
|  127  |  | 
|  128  |  | 
|  129   class Event { |  | 
|  130    public: |  | 
|  131     enum Type { SCAVENGER = 0, MARK_COMPACTOR = 1, START = 2 }; |  | 
|  132  |  | 
|  133     // Default constructor leaves the event uninitialized. |  | 
|  134     Event() {} |  | 
|  135  |  | 
|  136     Event(Type type, const char* gc_reason, const char* collector_reason); |  | 
|  137  |  | 
|  138     // Returns a string describing the event type. |  | 
|  139     const char* TypeName(bool short_name) const; |  | 
|  140  |  | 
|  141     // Type of event |  | 
|  142     Type type; |  | 
|  143  |  | 
|  144     const char* gc_reason; |  | 
|  145     const char* collector_reason; |  | 
|  146  |  | 
|  147     // Timestamp set in the constructor. |  | 
|  148     double start_time; |  | 
|  149  |  | 
|  150     // Timestamp set in the destructor. |  | 
|  151     double end_time; |  | 
|  152  |  | 
|  153     // Size of objects in heap set in constructor. |  | 
|  154     intptr_t start_object_size; |  | 
|  155  |  | 
|  156     // Size of objects in heap set in destructor. |  | 
|  157     intptr_t end_object_size; |  | 
|  158  |  | 
|  159     // Size of memory allocated from OS set in constructor. |  | 
|  160     intptr_t start_memory_size; |  | 
|  161  |  | 
|  162     // Size of memory allocated from OS set in destructor. |  | 
|  163     intptr_t end_memory_size; |  | 
|  164  |  | 
|  165     // Total amount of space either wasted or contained in one of free lists |  | 
|  166     // before the current GC. |  | 
|  167     intptr_t start_holes_size; |  | 
|  168  |  | 
|  169     // Total amount of space either wasted or contained in one of free lists |  | 
|  170     // after the current GC. |  | 
|  171     intptr_t end_holes_size; |  | 
|  172  |  | 
|  173     // Number of incremental marking steps since creation of tracer. |  | 
|  174     // (value at start of event) |  | 
|  175     int cumulative_incremental_marking_steps; |  | 
|  176  |  | 
|  177     // Incremental marking steps since |  | 
|  178     // - last event for SCAVENGER events |  | 
|  179     // - last MARK_COMPACTOR event for MARK_COMPACTOR events |  | 
|  180     int incremental_marking_steps; |  | 
|  181  |  | 
|  182     // Bytes marked since creation of tracer (value at start of event). |  | 
|  183     intptr_t cumulative_incremental_marking_bytes; |  | 
|  184  |  | 
|  185     // Bytes marked since |  | 
|  186     // - last event for SCAVENGER events |  | 
|  187     // - last MARK_COMPACTOR event for MARK_COMPACTOR events |  | 
|  188     intptr_t incremental_marking_bytes; |  | 
|  189  |  | 
|  190     // Cumulative duration of incremental marking steps since creation of |  | 
|  191     // tracer. (value at start of event) |  | 
|  192     double cumulative_incremental_marking_duration; |  | 
|  193  |  | 
|  194     // Duration of incremental marking steps since |  | 
|  195     // - last event for SCAVENGER events |  | 
|  196     // - last MARK_COMPACTOR event for MARK_COMPACTOR events |  | 
|  197     double incremental_marking_duration; |  | 
|  198  |  | 
|  199     // Longest incremental marking step since start of marking. |  | 
|  200     // (value at start of event) |  | 
|  201     double longest_incremental_marking_step; |  | 
|  202  |  | 
|  203     // Amounts of time spent in different scopes during GC. |  | 
|  204     double scopes[Scope::NUMBER_OF_SCOPES]; |  | 
|  205   }; |  | 
|  206  |  | 
|  207   static const int kRingBufferMaxSize = 10; |  | 
|  208  |  | 
|  209   typedef RingBuffer<Event, kRingBufferMaxSize> EventBuffer; |  | 
|  210  |  | 
|  211   explicit GCTracer(Heap* heap); |  | 
|  212  |  | 
|  213   // Start collecting data. |  | 
|  214   void Start(GarbageCollector collector, const char* gc_reason, |  | 
|  215              const char* collector_reason); |  | 
|  216  |  | 
|  217   // Stop collecting data and print results. |  | 
|  218   void Stop(); |  | 
|  219  |  | 
|  220   // Log an incremental marking step. |  | 
|  221   void AddIncrementalMarkingStep(double duration, intptr_t bytes); |  | 
|  222  |  | 
|  223   // Log time spent in marking. |  | 
|  224   void AddMarkingTime(double duration) { |  | 
|  225     cumulative_marking_duration_ += duration; |  | 
|  226   } |  | 
|  227  |  | 
|  228   // Time spent in marking. |  | 
|  229   double cumulative_marking_duration() const { |  | 
|  230     return cumulative_marking_duration_; |  | 
|  231   } |  | 
|  232  |  | 
|  233   // Log time spent in sweeping on main thread. |  | 
|  234   void AddSweepingTime(double duration) { |  | 
|  235     cumulative_sweeping_duration_ += duration; |  | 
|  236   } |  | 
|  237  |  | 
|  238   // Time spent in sweeping on main thread. |  | 
|  239   double cumulative_sweeping_duration() const { |  | 
|  240     return cumulative_sweeping_duration_; |  | 
|  241   } |  | 
|  242  |  | 
|  243   // Compute the mean duration of the last scavenger events. Returns 0 if no |  | 
|  244   // events have been recorded. |  | 
|  245   double MeanScavengerDuration() const { |  | 
|  246     return MeanDuration(scavenger_events_); |  | 
|  247   } |  | 
|  248  |  | 
|  249   // Compute the max duration of the last scavenger events. Returns 0 if no |  | 
|  250   // events have been recorded. |  | 
|  251   double MaxScavengerDuration() const { return MaxDuration(scavenger_events_); } |  | 
|  252  |  | 
|  253   // Compute the mean duration of the last mark compactor events. Returns 0 if |  | 
|  254   // no events have been recorded. |  | 
|  255   double MeanMarkCompactorDuration() const { |  | 
|  256     return MeanDuration(mark_compactor_events_); |  | 
|  257   } |  | 
|  258  |  | 
|  259   // Compute the max duration of the last mark compactor events. Return 0 if no |  | 
|  260   // events have been recorded. |  | 
|  261   double MaxMarkCompactorDuration() const { |  | 
|  262     return MaxDuration(mark_compactor_events_); |  | 
|  263   } |  | 
|  264  |  | 
|  265   // Compute the mean step duration of the last incremental marking round. |  | 
|  266   // Returns 0 if no incremental marking round has been completed. |  | 
|  267   double MeanIncrementalMarkingDuration() const; |  | 
|  268  |  | 
|  269   // Compute the max step duration of the last incremental marking round. |  | 
|  270   // Returns 0 if no incremental marking round has been completed. |  | 
|  271   double MaxIncrementalMarkingDuration() const; |  | 
|  272  |  | 
|  273   // Compute the average incremental marking speed in bytes/second. Returns 0 if |  | 
|  274   // no events have been recorded. |  | 
|  275   intptr_t IncrementalMarkingSpeedInBytesPerMillisecond() const; |  | 
|  276  |  | 
|  277  private: |  | 
|  278   // Print one detailed trace line in name=value format. |  | 
|  279   // TODO(ernstm): Move to Heap. |  | 
|  280   void PrintNVP() const; |  | 
|  281  |  | 
|  282   // Print one trace line. |  | 
|  283   // TODO(ernstm): Move to Heap. |  | 
|  284   void Print() const; |  | 
|  285  |  | 
|  286   // Compute the mean duration of the events in the given ring buffer. |  | 
|  287   double MeanDuration(const EventBuffer& events) const; |  | 
|  288  |  | 
|  289   // Compute the max duration of the events in the given ring buffer. |  | 
|  290   double MaxDuration(const EventBuffer& events) const; |  | 
|  291  |  | 
|  292   // Pointer to the heap that owns this tracer. |  | 
|  293   Heap* heap_; |  | 
|  294  |  | 
|  295   // Current tracer event. Populated during Start/Stop cycle. Valid after Stop() |  | 
|  296   // has returned. |  | 
|  297   Event current_; |  | 
|  298  |  | 
|  299   // Previous tracer event. |  | 
|  300   Event previous_; |  | 
|  301  |  | 
|  302   // Previous MARK_COMPACTOR event. |  | 
|  303   Event previous_mark_compactor_event_; |  | 
|  304  |  | 
|  305   // RingBuffers for SCAVENGER events. |  | 
|  306   EventBuffer scavenger_events_; |  | 
|  307  |  | 
|  308   // RingBuffers for MARK_COMPACTOR events. |  | 
|  309   EventBuffer mark_compactor_events_; |  | 
|  310  |  | 
|  311   // Cumulative number of incremental marking steps since creation of tracer. |  | 
|  312   int cumulative_incremental_marking_steps_; |  | 
|  313  |  | 
|  314   // Cumulative size of incremental marking steps (in bytes) since creation of |  | 
|  315   // tracer. |  | 
|  316   intptr_t cumulative_incremental_marking_bytes_; |  | 
|  317  |  | 
|  318   // Cumulative duration of incremental marking steps since creation of tracer. |  | 
|  319   double cumulative_incremental_marking_duration_; |  | 
|  320  |  | 
|  321   // Longest incremental marking step since start of marking. |  | 
|  322   double longest_incremental_marking_step_; |  | 
|  323  |  | 
|  324   // Total marking time. |  | 
|  325   // This timer is precise when run with --print-cumulative-gc-stat |  | 
|  326   double cumulative_marking_duration_; |  | 
|  327  |  | 
|  328   // Total sweeping time on the main thread. |  | 
|  329   // This timer is precise when run with --print-cumulative-gc-stat |  | 
|  330   // TODO(hpayer): Account for sweeping time on sweeper threads. Add a |  | 
|  331   // different field for that. |  | 
|  332   // TODO(hpayer): This timer right now just holds the sweeping time |  | 
|  333   // of the initial atomic sweeping pause. Make sure that it accumulates |  | 
|  334   // all sweeping operations performed on the main thread. |  | 
|  335   double cumulative_sweeping_duration_; |  | 
|  336  |  | 
|  337   DISALLOW_COPY_AND_ASSIGN(GCTracer); |  | 
|  338 }; |  | 
|  339 } |  | 
|  340 }  // namespace v8::internal |  | 
|  341  |  | 
|  342 #endif  // V8_GC_TRACER_H_ |  | 
| OLD | NEW |