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 ASSERT(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 incremental_marking_steps; |
| 176 |
| 177 // Cumulative duration of incremental marking steps since creation of |
| 178 // tracer. (value at start of event) |
| 179 double incremental_marking_duration; |
| 180 |
| 181 // Longest incremental marking step since start of marking. |
| 182 // (value at start of event) |
| 183 double longest_incremental_marking_step; |
| 184 |
| 185 // Amounts of time spent in different scopes during GC. |
| 186 double scopes[Scope::NUMBER_OF_SCOPES]; |
| 187 }; |
| 188 |
| 189 static const int kRingBufferMaxSize = 10; |
| 190 |
| 191 typedef RingBuffer<Event, kRingBufferMaxSize> EventBuffer; |
| 192 |
| 193 explicit GCTracer(Heap* heap); |
| 194 |
| 195 // Start collecting data. |
| 196 void Start(GarbageCollector collector, const char* gc_reason, |
| 197 const char* collector_reason); |
| 198 |
| 199 // Stop collecting data and print results. |
| 200 void Stop(); |
| 201 |
| 202 // Log an incremental marking step. |
| 203 void AddIncrementalMarkingStep(double duration); |
| 204 |
| 205 private: |
| 206 // Print one detailed trace line in name=value format. |
| 207 // TODO(ernstm): Move to Heap. |
| 208 void PrintNVP() const; |
| 209 |
| 210 // Print one trace line. |
| 211 // TODO(ernstm): Move to Heap. |
| 212 void Print() const; |
| 213 |
| 214 // Pointer to the heap that owns this tracer. |
| 215 Heap* heap_; |
| 216 |
| 217 // Current tracer event. Populated during Start/Stop cycle. Valid after Stop() |
| 218 // has returned. |
| 219 Event current_; |
| 220 |
| 221 // Previous tracer event. |
| 222 Event previous_; |
| 223 |
| 224 // Previous MARK_COMPACTOR event. |
| 225 Event previous_mark_compactor_event_; |
| 226 |
| 227 // RingBuffers for SCAVENGER events. |
| 228 EventBuffer scavenger_events_; |
| 229 |
| 230 // RingBuffers for MARK_COMPACTOR events. |
| 231 EventBuffer mark_compactor_events_; |
| 232 |
| 233 // Cumulative number of incremental marking steps since creation of tracer. |
| 234 int incremental_marking_steps_; |
| 235 |
| 236 // Cumulative duration of incremental marking steps since creation of tracer. |
| 237 double incremental_marking_duration_; |
| 238 |
| 239 // Longest incremental marking step since start of marking. |
| 240 double longest_incremental_marking_step_; |
| 241 |
| 242 DISALLOW_COPY_AND_ASSIGN(GCTracer); |
| 243 }; |
| 244 } |
| 245 } // namespace v8::internal |
| 246 |
| 247 #endif // V8_GC_TRACER_H_ |
OLD | NEW |