10d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko// Copyright 2015 The Chromium Authors. All rights reserved. 20d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko// Use of this source code is governed by a BSD-style license that can be 30d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko// found in the LICENSE file. 40d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 50d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/trace_event/trace_buffer.h" 60d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 794ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory> 80d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <utility> 90d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include <vector> 100d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 110d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/macros.h" 1294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/trace_event/heap_profiler.h" 130d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/trace_event/trace_event_impl.h" 140d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 150d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkonamespace base { 160d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkonamespace trace_event { 170d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 180d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkonamespace { 190d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 200d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkoclass TraceBufferRingBuffer : public TraceBuffer { 210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko public: 220d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceBufferRingBuffer(size_t max_chunks) 230d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko : max_chunks_(max_chunks), 240d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko recyclable_chunks_queue_(new size_t[queue_capacity()]), 250d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko queue_head_(0), 260d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko queue_tail_(max_chunks), 270d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko current_iteration_index_(0), 280d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko current_chunk_seq_(1) { 290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunks_.reserve(max_chunks); 300d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko for (size_t i = 0; i < max_chunks; ++i) 310d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko recyclable_chunks_queue_[i] = i; 320d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 330d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) override { 3594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez HEAP_PROFILER_SCOPED_IGNORE; 3694ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 370d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // Because the number of threads is much less than the number of chunks, 380d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // the queue should never be empty. 390d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK(!QueueIsEmpty()); 400d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 410d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko *index = recyclable_chunks_queue_[queue_head_]; 420d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko queue_head_ = NextQueueIndex(queue_head_); 430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko current_iteration_index_ = queue_head_; 440d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 450d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (*index >= chunks_.size()) 460d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunks_.resize(*index + 1); 470d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 480d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceBufferChunk* chunk = chunks_[*index].release(); 490d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunks_[*index] = NULL; // Put NULL in the slot of a in-flight chunk. 500d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (chunk) 510d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunk->Reset(current_chunk_seq_++); 520d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko else 530d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunk = new TraceBufferChunk(current_chunk_seq_++); 540d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 5594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return std::unique_ptr<TraceBufferChunk>(chunk); 560d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 570d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 5894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez void ReturnChunk(size_t index, 5994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<TraceBufferChunk> chunk) override { 600d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // When this method is called, the queue should not be full because it 610d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // can contain all chunks including the one to be returned. 620d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK(!QueueIsFull()); 630d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK(chunk); 640d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK_LT(index, chunks_.size()); 650d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK(!chunks_[index]); 660d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunks_[index] = std::move(chunk); 670d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko recyclable_chunks_queue_[queue_tail_] = index; 680d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko queue_tail_ = NextQueueIndex(queue_tail_); 690d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 700d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 710d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko bool IsFull() const override { return false; } 720d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 730d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t Size() const override { 740d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // This is approximate because not all of the chunks are full. 750d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize; 760d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 770d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 780d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t Capacity() const override { 790d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize; 800d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 810d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 820d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceEvent* GetEventByHandle(TraceEventHandle handle) override { 830d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (handle.chunk_index >= chunks_.size()) 840d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return NULL; 850d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceBufferChunk* chunk = chunks_[handle.chunk_index].get(); 860d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (!chunk || chunk->seq() != handle.chunk_seq) 870d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return NULL; 880d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return chunk->GetEventAt(handle.event_index); 890d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 900d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 910d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const TraceBufferChunk* NextChunk() override { 920d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (chunks_.empty()) 930d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return NULL; 940d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 950d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko while (current_iteration_index_ != queue_tail_) { 960d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t chunk_index = recyclable_chunks_queue_[current_iteration_index_]; 970d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko current_iteration_index_ = NextQueueIndex(current_iteration_index_); 980d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. 990d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko continue; 1000d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK(chunks_[chunk_index]); 1010d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return chunks_[chunk_index].get(); 1020d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1030d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return NULL; 1040d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1050d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1060d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko void EstimateTraceMemoryOverhead( 1070d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceEventMemoryOverhead* overhead) override { 1080d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko overhead->Add("TraceBufferRingBuffer", sizeof(*this)); 1090d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko for (size_t queue_index = queue_head_; queue_index != queue_tail_; 1100d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko queue_index = NextQueueIndex(queue_index)) { 1110d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t chunk_index = recyclable_chunks_queue_[queue_index]; 1120d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (chunk_index >= chunks_.size()) // Skip uninitialized chunks. 1130d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko continue; 1140d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunks_[chunk_index]->EstimateTraceMemoryOverhead(overhead); 1150d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1160d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1170d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1180d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko private: 1190d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko bool QueueIsEmpty() const { return queue_head_ == queue_tail_; } 1200d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t QueueSize() const { 1220d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return queue_tail_ > queue_head_ 1230d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko ? queue_tail_ - queue_head_ 1240d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko : queue_tail_ + queue_capacity() - queue_head_; 1250d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1260d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1270d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko bool QueueIsFull() const { return QueueSize() == queue_capacity() - 1; } 1280d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t queue_capacity() const { 1300d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // One extra space to help distinguish full state and empty state. 1310d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return max_chunks_ + 1; 1320d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1330d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1340d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t NextQueueIndex(size_t index) const { 1350d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko index++; 1360d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (index >= queue_capacity()) 1370d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko index = 0; 1380d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return index; 1390d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1400d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1410d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t max_chunks_; 14294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::vector<std::unique_ptr<TraceBufferChunk>> chunks_; 1430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 14494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<size_t[]> recyclable_chunks_queue_; 1450d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t queue_head_; 1460d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t queue_tail_; 1470d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1480d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t current_iteration_index_; 1490d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko uint32_t current_chunk_seq_; 1500d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1510d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DISALLOW_COPY_AND_ASSIGN(TraceBufferRingBuffer); 1520d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko}; 1530d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1540d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkoclass TraceBufferVector : public TraceBuffer { 1550d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko public: 1560d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceBufferVector(size_t max_chunks) 1570d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko : in_flight_chunk_count_(0), 1580d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko current_iteration_index_(0), 1590d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko max_chunks_(max_chunks) { 1600d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunks_.reserve(max_chunks_); 1610d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1620d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 16394ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) override { 16494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez HEAP_PROFILER_SCOPED_IGNORE; 16594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez 1660d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // This function may be called when adding normal events or indirectly from 1670d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // AddMetadataEventsWhileLocked(). We can not DECHECK(!IsFull()) because we 1680d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // have to add the metadata events and flush thread-local buffers even if 1690d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // the buffer is full. 1700d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko *index = chunks_.size(); 1710d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunks_.push_back(NULL); // Put NULL in the slot of a in-flight chunk. 1720d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko ++in_flight_chunk_count_; 1730d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // + 1 because zero chunk_seq is not allowed. 17494ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez return std::unique_ptr<TraceBufferChunk>( 1750d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko new TraceBufferChunk(static_cast<uint32_t>(*index) + 1)); 1760d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1770d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 17894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez void ReturnChunk(size_t index, 17994ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez std::unique_ptr<TraceBufferChunk> chunk) override { 1800d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK_GT(in_flight_chunk_count_, 0u); 1810d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK_LT(index, chunks_.size()); 1820d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK(!chunks_[index]); 1830d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko --in_flight_chunk_count_; 1840d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunks_[index] = chunk.release(); 1850d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1860d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1870d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko bool IsFull() const override { return chunks_.size() >= max_chunks_; } 1880d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1890d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t Size() const override { 1900d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // This is approximate because not all of the chunks are full. 1910d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize; 1920d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1930d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1940d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t Capacity() const override { 1950d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize; 1960d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 1970d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 1980d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceEvent* GetEventByHandle(TraceEventHandle handle) override { 1990d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (handle.chunk_index >= chunks_.size()) 2000d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return NULL; 2010d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceBufferChunk* chunk = chunks_[handle.chunk_index]; 2020d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (!chunk || chunk->seq() != handle.chunk_seq) 2030d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return NULL; 2040d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return chunk->GetEventAt(handle.event_index); 2050d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 2060d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2070d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const TraceBufferChunk* NextChunk() override { 2080d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko while (current_iteration_index_ < chunks_.size()) { 2090d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // Skip in-flight chunks. 2100d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const TraceBufferChunk* chunk = chunks_[current_iteration_index_++]; 2110d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (chunk) 2120d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return chunk; 2130d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 2140d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return NULL; 2150d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 2160d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2170d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko void EstimateTraceMemoryOverhead( 2180d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceEventMemoryOverhead* overhead) override { 2190d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const size_t chunks_ptr_vector_allocated_size = 2200d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko sizeof(*this) + max_chunks_ * sizeof(decltype(chunks_)::value_type); 2210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const size_t chunks_ptr_vector_resident_size = 2220d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko sizeof(*this) + chunks_.size() * sizeof(decltype(chunks_)::value_type); 2230d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko overhead->Add("TraceBufferVector", chunks_ptr_vector_allocated_size, 2240d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunks_ptr_vector_resident_size); 2250d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko for (size_t i = 0; i < chunks_.size(); ++i) { 2260d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceBufferChunk* chunk = chunks_[i]; 2270d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // Skip the in-flight (nullptr) chunks. They will be accounted by the 2280d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // per-thread-local dumpers, see ThreadLocalEventBuffer::OnMemoryDump. 2290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (chunk) 2300d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunk->EstimateTraceMemoryOverhead(overhead); 2310d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 2320d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 2330d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2340d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko private: 2350d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t in_flight_chunk_count_; 2360d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t current_iteration_index_; 2370d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko size_t max_chunks_; 2380d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko ScopedVector<TraceBufferChunk> chunks_; 2390d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2400d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DISALLOW_COPY_AND_ASSIGN(TraceBufferVector); 2410d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko}; 2420d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} // namespace 2440d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2450d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoTraceBufferChunk::TraceBufferChunk(uint32_t seq) : next_free_(0), seq_(seq) {} 2460d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2470d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoTraceBufferChunk::~TraceBufferChunk() {} 2480d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2490d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid TraceBufferChunk::Reset(uint32_t new_seq) { 2500d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko for (size_t i = 0; i < next_free_; ++i) 2510d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunk_[i].Reset(); 2520d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko next_free_ = 0; 2530d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko seq_ = new_seq; 2540d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko cached_overhead_estimate_.reset(); 2550d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 2560d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2570d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoTraceEvent* TraceBufferChunk::AddTraceEvent(size_t* event_index) { 2580d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK(!IsFull()); 2590d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko *event_index = next_free_++; 2600d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return &chunk_[*event_index]; 2610d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 2620d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2630d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid TraceBufferChunk::EstimateTraceMemoryOverhead( 2640d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko TraceEventMemoryOverhead* overhead) { 2650d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (!cached_overhead_estimate_) { 2660d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko cached_overhead_estimate_.reset(new TraceEventMemoryOverhead); 2670d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2680d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // When estimating the size of TraceBufferChunk, exclude the array of trace 2690d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // events, as they are computed individually below. 2700d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko cached_overhead_estimate_->Add("TraceBufferChunk", 2710d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko sizeof(*this) - sizeof(chunk_)); 2720d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 2730d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2740d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const size_t num_cached_estimated_events = 2750d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko cached_overhead_estimate_->GetCount("TraceEvent"); 2760d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko DCHECK_LE(num_cached_estimated_events, size()); 2770d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2780d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (IsFull() && num_cached_estimated_events == size()) { 2790d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko overhead->Update(*cached_overhead_estimate_); 2800d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return; 2810d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 2820d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2830d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko for (size_t i = num_cached_estimated_events; i < size(); ++i) 2840d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko chunk_[i].EstimateTraceMemoryOverhead(cached_overhead_estimate_.get()); 2850d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2860d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (IsFull()) { 2870d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko cached_overhead_estimate_->AddSelf(); 2880d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } else { 2890d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // The unused TraceEvents in |chunks_| are not cached. They will keep 2900d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // changing as new TraceEvents are added to this chunk, so they are 2910d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // computed on the fly. 2920d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const size_t num_unused_trace_events = capacity() - size(); 2930d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko overhead->Add("TraceEvent (unused)", 2940d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko num_unused_trace_events * sizeof(TraceEvent)); 2950d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko } 2960d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 2970d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko overhead->Update(*cached_overhead_estimate_); 2980d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 2990d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3000d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoTraceResultBuffer::OutputCallback 3010d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoTraceResultBuffer::SimpleOutput::GetCallback() { 3020d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return Bind(&SimpleOutput::Append, Unretained(this)); 3030d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 3040d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3050d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid TraceResultBuffer::SimpleOutput::Append( 3060d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const std::string& json_trace_output) { 3070d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko json_output += json_trace_output; 3080d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 3090d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3100d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoTraceResultBuffer::TraceResultBuffer() : append_comma_(false) {} 3110d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3120d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoTraceResultBuffer::~TraceResultBuffer() {} 3130d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3140d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid TraceResultBuffer::SetOutputCallback( 3150d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const OutputCallback& json_chunk_callback) { 3160d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko output_callback_ = json_chunk_callback; 3170d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 3180d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3190d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid TraceResultBuffer::Start() { 3200d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko append_comma_ = false; 3210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko output_callback_.Run("["); 3220d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 3230d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3240d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid TraceResultBuffer::AddFragment(const std::string& trace_fragment) { 3250d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (append_comma_) 3260d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko output_callback_.Run(","); 3270d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko append_comma_ = true; 3280d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko output_callback_.Run(trace_fragment); 3290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 3300d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3310d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid TraceResultBuffer::Finish() { 3320d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko output_callback_.Run("]"); 3330d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 3340d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3350d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoTraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer(size_t max_chunks) { 3360d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return new TraceBufferRingBuffer(max_chunks); 3370d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 3380d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3390d205d712abd16eeed2f5d5b1052a367d23a223fAlex VakulenkoTraceBuffer* TraceBuffer::CreateTraceBufferVectorOfSize(size_t max_chunks) { 3400d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return new TraceBufferVector(max_chunks); 3410d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 3420d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 3430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} // namespace trace_event 3440d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} // namespace base 345