| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/trace_event/trace_buffer.h" | 5 #include "base/trace_event/trace_buffer.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 #include <vector> |
| 8 | 9 |
| 9 #include "base/memory/scoped_vector.h" | 10 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/trace_event/trace_event_impl.h" | 11 #include "base/trace_event/trace_event_impl.h" |
| 11 | 12 |
| 12 namespace base { | 13 namespace base { |
| 13 namespace trace_event { | 14 namespace trace_event { |
| 14 | 15 |
| 15 namespace { | 16 namespace { |
| 16 | 17 |
| 17 class TraceBufferRingBuffer : public TraceBuffer { | 18 class TraceBufferRingBuffer : public TraceBuffer { |
| 18 public: | 19 public: |
| 19 TraceBufferRingBuffer(size_t max_chunks) | 20 TraceBufferRingBuffer(size_t max_chunks) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 33 // the queue should never be empty. | 34 // the queue should never be empty. |
| 34 DCHECK(!QueueIsEmpty()); | 35 DCHECK(!QueueIsEmpty()); |
| 35 | 36 |
| 36 *index = recyclable_chunks_queue_[queue_head_]; | 37 *index = recyclable_chunks_queue_[queue_head_]; |
| 37 queue_head_ = NextQueueIndex(queue_head_); | 38 queue_head_ = NextQueueIndex(queue_head_); |
| 38 current_iteration_index_ = queue_head_; | 39 current_iteration_index_ = queue_head_; |
| 39 | 40 |
| 40 if (*index >= chunks_.size()) | 41 if (*index >= chunks_.size()) |
| 41 chunks_.resize(*index + 1); | 42 chunks_.resize(*index + 1); |
| 42 | 43 |
| 43 TraceBufferChunk* chunk = chunks_[*index]; | 44 TraceBufferChunk* chunk = chunks_[*index].release(); |
| 44 chunks_[*index] = NULL; // Put NULL in the slot of a in-flight chunk. | 45 chunks_[*index] = NULL; // Put NULL in the slot of a in-flight chunk. |
| 45 if (chunk) | 46 if (chunk) |
| 46 chunk->Reset(current_chunk_seq_++); | 47 chunk->Reset(current_chunk_seq_++); |
| 47 else | 48 else |
| 48 chunk = new TraceBufferChunk(current_chunk_seq_++); | 49 chunk = new TraceBufferChunk(current_chunk_seq_++); |
| 49 | 50 |
| 50 return scoped_ptr<TraceBufferChunk>(chunk); | 51 return scoped_ptr<TraceBufferChunk>(chunk); |
| 51 } | 52 } |
| 52 | 53 |
| 53 void ReturnChunk(size_t index, scoped_ptr<TraceBufferChunk> chunk) override { | 54 void ReturnChunk(size_t index, scoped_ptr<TraceBufferChunk> chunk) override { |
| 54 // When this method is called, the queue should not be full because it | 55 // When this method is called, the queue should not be full because it |
| 55 // can contain all chunks including the one to be returned. | 56 // can contain all chunks including the one to be returned. |
| 56 DCHECK(!QueueIsFull()); | 57 DCHECK(!QueueIsFull()); |
| 57 DCHECK(chunk); | 58 DCHECK(chunk); |
| 58 DCHECK_LT(index, chunks_.size()); | 59 DCHECK_LT(index, chunks_.size()); |
| 59 DCHECK(!chunks_[index]); | 60 DCHECK(!chunks_[index]); |
| 60 chunks_[index] = chunk.release(); | 61 chunks_[index] = std::move(chunk); |
| 61 recyclable_chunks_queue_[queue_tail_] = index; | 62 recyclable_chunks_queue_[queue_tail_] = index; |
| 62 queue_tail_ = NextQueueIndex(queue_tail_); | 63 queue_tail_ = NextQueueIndex(queue_tail_); |
| 63 } | 64 } |
| 64 | 65 |
| 65 bool IsFull() const override { return false; } | 66 bool IsFull() const override { return false; } |
| 66 | 67 |
| 67 size_t Size() const override { | 68 size_t Size() const override { |
| 68 // This is approximate because not all of the chunks are full. | 69 // This is approximate because not all of the chunks are full. |
| 69 return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize; | 70 return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize; |
| 70 } | 71 } |
| 71 | 72 |
| 72 size_t Capacity() const override { | 73 size_t Capacity() const override { |
| 73 return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize; | 74 return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize; |
| 74 } | 75 } |
| 75 | 76 |
| 76 TraceEvent* GetEventByHandle(TraceEventHandle handle) override { | 77 TraceEvent* GetEventByHandle(TraceEventHandle handle) override { |
| 77 if (handle.chunk_index >= chunks_.size()) | 78 if (handle.chunk_index >= chunks_.size()) |
| 78 return NULL; | 79 return NULL; |
| 79 TraceBufferChunk* chunk = chunks_[handle.chunk_index]; | 80 TraceBufferChunk* chunk = chunks_[handle.chunk_index].get(); |
| 80 if (!chunk || chunk->seq() != handle.chunk_seq) | 81 if (!chunk || chunk->seq() != handle.chunk_seq) |
| 81 return NULL; | 82 return NULL; |
| 82 return chunk->GetEventAt(handle.event_index); | 83 return chunk->GetEventAt(handle.event_index); |
| 83 } | 84 } |
| 84 | 85 |
| 85 const TraceBufferChunk* NextChunk() override { | 86 const TraceBufferChunk* NextChunk() override { |
| 86 if (chunks_.empty()) | 87 if (chunks_.empty()) |
| 87 return NULL; | 88 return NULL; |
| 88 | 89 |
| 89 while (current_iteration_index_ != queue_tail_) { | 90 while (current_iteration_index_ != queue_tail_) { |
| 90 size_t chunk_index = recyclable_chunks_queue_[current_iteration_index_]; | 91 size_t chunk_index = recyclable_chunks_queue_[current_iteration_index_]; |
| 91 current_iteration_index_ = NextQueueIndex(current_iteration_index_); | 92 current_iteration_index_ = NextQueueIndex(current_iteration_index_); |
| 92 if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. | 93 if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. |
| 93 continue; | 94 continue; |
| 94 DCHECK(chunks_[chunk_index]); | 95 DCHECK(chunks_[chunk_index]); |
| 95 return chunks_[chunk_index]; | 96 return chunks_[chunk_index].get(); |
| 96 } | 97 } |
| 97 return NULL; | 98 return NULL; |
| 98 } | 99 } |
| 99 | 100 |
| 100 scoped_ptr<TraceBuffer> CloneForIteration() const override { | 101 scoped_ptr<TraceBuffer> CloneForIteration() const override { |
| 101 scoped_ptr<ClonedTraceBuffer> cloned_buffer(new ClonedTraceBuffer()); | 102 scoped_ptr<ClonedTraceBuffer> cloned_buffer(new ClonedTraceBuffer()); |
| 102 for (size_t queue_index = queue_head_; queue_index != queue_tail_; | 103 for (size_t queue_index = queue_head_; queue_index != queue_tail_; |
| 103 queue_index = NextQueueIndex(queue_index)) { | 104 queue_index = NextQueueIndex(queue_index)) { |
| 104 size_t chunk_index = recyclable_chunks_queue_[queue_index]; | 105 size_t chunk_index = recyclable_chunks_queue_[queue_index]; |
| 105 if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. | 106 if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. |
| 106 continue; | 107 continue; |
| 107 TraceBufferChunk* chunk = chunks_[chunk_index]; | 108 TraceBufferChunk* chunk = chunks_[chunk_index].get(); |
| 108 cloned_buffer->chunks_.push_back(chunk ? chunk->Clone().release() : NULL); | 109 cloned_buffer->chunks_.push_back(chunk ? chunk->Clone() : NULL); |
| 109 } | 110 } |
| 110 return std::move(cloned_buffer); | 111 return std::move(cloned_buffer); |
| 111 } | 112 } |
| 112 | 113 |
| 113 void EstimateTraceMemoryOverhead( | 114 void EstimateTraceMemoryOverhead( |
| 114 TraceEventMemoryOverhead* overhead) override { | 115 TraceEventMemoryOverhead* overhead) override { |
| 115 overhead->Add("TraceBufferRingBuffer", sizeof(*this)); | 116 overhead->Add("TraceBufferRingBuffer", sizeof(*this)); |
| 116 for (size_t queue_index = queue_head_; queue_index != queue_tail_; | 117 for (size_t queue_index = queue_head_; queue_index != queue_tail_; |
| 117 queue_index = NextQueueIndex(queue_index)) { | 118 queue_index = NextQueueIndex(queue_index)) { |
| 118 size_t chunk_index = recyclable_chunks_queue_[queue_index]; | 119 size_t chunk_index = recyclable_chunks_queue_[queue_index]; |
| 119 if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. | 120 if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. |
| 120 continue; | 121 continue; |
| 121 chunks_[chunk_index]->EstimateTraceMemoryOverhead(overhead); | 122 chunks_[chunk_index]->EstimateTraceMemoryOverhead(overhead); |
| 122 } | 123 } |
| 123 } | 124 } |
| 124 | 125 |
| 125 private: | 126 private: |
| 126 class ClonedTraceBuffer : public TraceBuffer { | 127 class ClonedTraceBuffer : public TraceBuffer { |
| 127 public: | 128 public: |
| 128 ClonedTraceBuffer() : current_iteration_index_(0) {} | 129 ClonedTraceBuffer() : current_iteration_index_(0) {} |
| 129 | 130 |
| 130 // The only implemented method. | 131 // The only implemented method. |
| 131 const TraceBufferChunk* NextChunk() override { | 132 const TraceBufferChunk* NextChunk() override { |
| 132 return current_iteration_index_ < chunks_.size() | 133 return current_iteration_index_ < chunks_.size() |
| 133 ? chunks_[current_iteration_index_++] | 134 ? chunks_[current_iteration_index_++].get() |
| 134 : NULL; | 135 : NULL; |
| 135 } | 136 } |
| 136 | 137 |
| 137 scoped_ptr<TraceBufferChunk> GetChunk(size_t* index) override { | 138 scoped_ptr<TraceBufferChunk> GetChunk(size_t* index) override { |
| 138 NOTIMPLEMENTED(); | 139 NOTIMPLEMENTED(); |
| 139 return scoped_ptr<TraceBufferChunk>(); | 140 return scoped_ptr<TraceBufferChunk>(); |
| 140 } | 141 } |
| 141 void ReturnChunk(size_t index, scoped_ptr<TraceBufferChunk>) override { | 142 void ReturnChunk(size_t index, scoped_ptr<TraceBufferChunk>) override { |
| 142 NOTIMPLEMENTED(); | 143 NOTIMPLEMENTED(); |
| 143 } | 144 } |
| 144 bool IsFull() const override { return false; } | 145 bool IsFull() const override { return false; } |
| 145 size_t Size() const override { return 0; } | 146 size_t Size() const override { return 0; } |
| 146 size_t Capacity() const override { return 0; } | 147 size_t Capacity() const override { return 0; } |
| 147 TraceEvent* GetEventByHandle(TraceEventHandle handle) override { | 148 TraceEvent* GetEventByHandle(TraceEventHandle handle) override { |
| 148 return NULL; | 149 return NULL; |
| 149 } | 150 } |
| 150 scoped_ptr<TraceBuffer> CloneForIteration() const override { | 151 scoped_ptr<TraceBuffer> CloneForIteration() const override { |
| 151 NOTIMPLEMENTED(); | 152 NOTIMPLEMENTED(); |
| 152 return scoped_ptr<TraceBuffer>(); | 153 return scoped_ptr<TraceBuffer>(); |
| 153 } | 154 } |
| 154 void EstimateTraceMemoryOverhead( | 155 void EstimateTraceMemoryOverhead( |
| 155 TraceEventMemoryOverhead* overhead) override { | 156 TraceEventMemoryOverhead* overhead) override { |
| 156 NOTIMPLEMENTED(); | 157 NOTIMPLEMENTED(); |
| 157 } | 158 } |
| 158 | 159 |
| 159 size_t current_iteration_index_; | 160 size_t current_iteration_index_; |
| 160 ScopedVector<TraceBufferChunk> chunks_; | 161 std::vector<scoped_ptr<TraceBufferChunk>> chunks_; |
| 161 }; | 162 }; |
| 162 | 163 |
| 163 bool QueueIsEmpty() const { return queue_head_ == queue_tail_; } | 164 bool QueueIsEmpty() const { return queue_head_ == queue_tail_; } |
| 164 | 165 |
| 165 size_t QueueSize() const { | 166 size_t QueueSize() const { |
| 166 return queue_tail_ > queue_head_ | 167 return queue_tail_ > queue_head_ |
| 167 ? queue_tail_ - queue_head_ | 168 ? queue_tail_ - queue_head_ |
| 168 : queue_tail_ + queue_capacity() - queue_head_; | 169 : queue_tail_ + queue_capacity() - queue_head_; |
| 169 } | 170 } |
| 170 | 171 |
| 171 bool QueueIsFull() const { return QueueSize() == queue_capacity() - 1; } | 172 bool QueueIsFull() const { return QueueSize() == queue_capacity() - 1; } |
| 172 | 173 |
| 173 size_t queue_capacity() const { | 174 size_t queue_capacity() const { |
| 174 // One extra space to help distinguish full state and empty state. | 175 // One extra space to help distinguish full state and empty state. |
| 175 return max_chunks_ + 1; | 176 return max_chunks_ + 1; |
| 176 } | 177 } |
| 177 | 178 |
| 178 size_t NextQueueIndex(size_t index) const { | 179 size_t NextQueueIndex(size_t index) const { |
| 179 index++; | 180 index++; |
| 180 if (index >= queue_capacity()) | 181 if (index >= queue_capacity()) |
| 181 index = 0; | 182 index = 0; |
| 182 return index; | 183 return index; |
| 183 } | 184 } |
| 184 | 185 |
| 185 size_t max_chunks_; | 186 size_t max_chunks_; |
| 186 ScopedVector<TraceBufferChunk> chunks_; | 187 std::vector<scoped_ptr<TraceBufferChunk>> chunks_; |
| 187 | 188 |
| 188 scoped_ptr<size_t[]> recyclable_chunks_queue_; | 189 scoped_ptr<size_t[]> recyclable_chunks_queue_; |
| 189 size_t queue_head_; | 190 size_t queue_head_; |
| 190 size_t queue_tail_; | 191 size_t queue_tail_; |
| 191 | 192 |
| 192 size_t current_iteration_index_; | 193 size_t current_iteration_index_; |
| 193 uint32 current_chunk_seq_; | 194 uint32 current_chunk_seq_; |
| 194 | 195 |
| 195 DISALLOW_COPY_AND_ASSIGN(TraceBufferRingBuffer); | 196 DISALLOW_COPY_AND_ASSIGN(TraceBufferRingBuffer); |
| 196 }; | 197 }; |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer(size_t max_chunks) { | 390 TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer(size_t max_chunks) { |
| 390 return new TraceBufferRingBuffer(max_chunks); | 391 return new TraceBufferRingBuffer(max_chunks); |
| 391 } | 392 } |
| 392 | 393 |
| 393 TraceBuffer* TraceBuffer::CreateTraceBufferVectorOfSize(size_t max_chunks) { | 394 TraceBuffer* TraceBuffer::CreateTraceBufferVectorOfSize(size_t max_chunks) { |
| 394 return new TraceBufferVector(max_chunks); | 395 return new TraceBufferVector(max_chunks); |
| 395 } | 396 } |
| 396 | 397 |
| 397 } // namespace trace_event | 398 } // namespace trace_event |
| 398 } // namespace base | 399 } // namespace base |
| OLD | NEW |