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