1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/trace_buffer.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <utility>
9*6777b538SAndroid Build Coastguard Worker #include <vector>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/heap_profiler.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/trace_event/trace_event_impl.h"
14*6777b538SAndroid Build Coastguard Worker
15*6777b538SAndroid Build Coastguard Worker namespace base {
16*6777b538SAndroid Build Coastguard Worker namespace trace_event {
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker namespace {
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Worker class TraceBufferRingBuffer : public TraceBuffer {
21*6777b538SAndroid Build Coastguard Worker public:
TraceBufferRingBuffer(size_t max_chunks)22*6777b538SAndroid Build Coastguard Worker TraceBufferRingBuffer(size_t max_chunks)
23*6777b538SAndroid Build Coastguard Worker : max_chunks_(max_chunks),
24*6777b538SAndroid Build Coastguard Worker recyclable_chunks_queue_(new size_t[queue_capacity()]),
25*6777b538SAndroid Build Coastguard Worker queue_head_(0),
26*6777b538SAndroid Build Coastguard Worker queue_tail_(max_chunks),
27*6777b538SAndroid Build Coastguard Worker current_iteration_index_(0),
28*6777b538SAndroid Build Coastguard Worker current_chunk_seq_(1) {
29*6777b538SAndroid Build Coastguard Worker chunks_.reserve(max_chunks);
30*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < max_chunks; ++i)
31*6777b538SAndroid Build Coastguard Worker recyclable_chunks_queue_[i] = i;
32*6777b538SAndroid Build Coastguard Worker }
33*6777b538SAndroid Build Coastguard Worker
34*6777b538SAndroid Build Coastguard Worker TraceBufferRingBuffer(const TraceBufferRingBuffer&) = delete;
35*6777b538SAndroid Build Coastguard Worker TraceBufferRingBuffer& operator=(const TraceBufferRingBuffer&) = delete;
36*6777b538SAndroid Build Coastguard Worker
GetChunk(size_t * index)37*6777b538SAndroid Build Coastguard Worker std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) override {
38*6777b538SAndroid Build Coastguard Worker HEAP_PROFILER_SCOPED_IGNORE;
39*6777b538SAndroid Build Coastguard Worker
40*6777b538SAndroid Build Coastguard Worker // Because the number of threads is much less than the number of chunks,
41*6777b538SAndroid Build Coastguard Worker // the queue should never be empty.
42*6777b538SAndroid Build Coastguard Worker DCHECK(!QueueIsEmpty());
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker *index = recyclable_chunks_queue_[queue_head_];
45*6777b538SAndroid Build Coastguard Worker queue_head_ = NextQueueIndex(queue_head_);
46*6777b538SAndroid Build Coastguard Worker current_iteration_index_ = queue_head_;
47*6777b538SAndroid Build Coastguard Worker
48*6777b538SAndroid Build Coastguard Worker if (*index >= chunks_.size())
49*6777b538SAndroid Build Coastguard Worker chunks_.resize(*index + 1);
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker TraceBufferChunk* chunk = chunks_[*index].release();
52*6777b538SAndroid Build Coastguard Worker chunks_[*index] = nullptr; // Put nullptr in the slot of a in-flight chunk.
53*6777b538SAndroid Build Coastguard Worker if (chunk)
54*6777b538SAndroid Build Coastguard Worker chunk->Reset(current_chunk_seq_++);
55*6777b538SAndroid Build Coastguard Worker else
56*6777b538SAndroid Build Coastguard Worker chunk = new TraceBufferChunk(current_chunk_seq_++);
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker return std::unique_ptr<TraceBufferChunk>(chunk);
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker
ReturnChunk(size_t index,std::unique_ptr<TraceBufferChunk> chunk)61*6777b538SAndroid Build Coastguard Worker void ReturnChunk(size_t index,
62*6777b538SAndroid Build Coastguard Worker std::unique_ptr<TraceBufferChunk> chunk) override {
63*6777b538SAndroid Build Coastguard Worker // When this method is called, the queue should not be full because it
64*6777b538SAndroid Build Coastguard Worker // can contain all chunks including the one to be returned.
65*6777b538SAndroid Build Coastguard Worker DCHECK(!QueueIsFull());
66*6777b538SAndroid Build Coastguard Worker DCHECK(chunk);
67*6777b538SAndroid Build Coastguard Worker DCHECK_LT(index, chunks_.size());
68*6777b538SAndroid Build Coastguard Worker DCHECK(!chunks_[index]);
69*6777b538SAndroid Build Coastguard Worker chunks_[index] = std::move(chunk);
70*6777b538SAndroid Build Coastguard Worker recyclable_chunks_queue_[queue_tail_] = index;
71*6777b538SAndroid Build Coastguard Worker queue_tail_ = NextQueueIndex(queue_tail_);
72*6777b538SAndroid Build Coastguard Worker }
73*6777b538SAndroid Build Coastguard Worker
IsFull() const74*6777b538SAndroid Build Coastguard Worker bool IsFull() const override { return false; }
75*6777b538SAndroid Build Coastguard Worker
Size() const76*6777b538SAndroid Build Coastguard Worker size_t Size() const override {
77*6777b538SAndroid Build Coastguard Worker // This is approximate because not all of the chunks are full.
78*6777b538SAndroid Build Coastguard Worker return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize;
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker
Capacity() const81*6777b538SAndroid Build Coastguard Worker size_t Capacity() const override {
82*6777b538SAndroid Build Coastguard Worker return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize;
83*6777b538SAndroid Build Coastguard Worker }
84*6777b538SAndroid Build Coastguard Worker
GetEventByHandle(TraceEventHandle handle)85*6777b538SAndroid Build Coastguard Worker TraceEvent* GetEventByHandle(TraceEventHandle handle) override {
86*6777b538SAndroid Build Coastguard Worker if (handle.chunk_index >= chunks_.size())
87*6777b538SAndroid Build Coastguard Worker return nullptr;
88*6777b538SAndroid Build Coastguard Worker TraceBufferChunk* chunk = chunks_[handle.chunk_index].get();
89*6777b538SAndroid Build Coastguard Worker if (!chunk || chunk->seq() != handle.chunk_seq)
90*6777b538SAndroid Build Coastguard Worker return nullptr;
91*6777b538SAndroid Build Coastguard Worker return chunk->GetEventAt(handle.event_index);
92*6777b538SAndroid Build Coastguard Worker }
93*6777b538SAndroid Build Coastguard Worker
NextChunk()94*6777b538SAndroid Build Coastguard Worker const TraceBufferChunk* NextChunk() override {
95*6777b538SAndroid Build Coastguard Worker if (chunks_.empty())
96*6777b538SAndroid Build Coastguard Worker return nullptr;
97*6777b538SAndroid Build Coastguard Worker
98*6777b538SAndroid Build Coastguard Worker while (current_iteration_index_ != queue_tail_) {
99*6777b538SAndroid Build Coastguard Worker size_t chunk_index = recyclable_chunks_queue_[current_iteration_index_];
100*6777b538SAndroid Build Coastguard Worker current_iteration_index_ = NextQueueIndex(current_iteration_index_);
101*6777b538SAndroid Build Coastguard Worker if (chunk_index >= chunks_.size()) // Skip uninitialized chunks.
102*6777b538SAndroid Build Coastguard Worker continue;
103*6777b538SAndroid Build Coastguard Worker DCHECK(chunks_[chunk_index]);
104*6777b538SAndroid Build Coastguard Worker return chunks_[chunk_index].get();
105*6777b538SAndroid Build Coastguard Worker }
106*6777b538SAndroid Build Coastguard Worker return nullptr;
107*6777b538SAndroid Build Coastguard Worker }
108*6777b538SAndroid Build Coastguard Worker
EstimateTraceMemoryOverhead(TraceEventMemoryOverhead * overhead)109*6777b538SAndroid Build Coastguard Worker void EstimateTraceMemoryOverhead(
110*6777b538SAndroid Build Coastguard Worker TraceEventMemoryOverhead* overhead) override {
111*6777b538SAndroid Build Coastguard Worker overhead->Add(TraceEventMemoryOverhead::kTraceBuffer, sizeof(*this));
112*6777b538SAndroid Build Coastguard Worker for (size_t queue_index = queue_head_; queue_index != queue_tail_;
113*6777b538SAndroid Build Coastguard Worker queue_index = NextQueueIndex(queue_index)) {
114*6777b538SAndroid Build Coastguard Worker size_t chunk_index = recyclable_chunks_queue_[queue_index];
115*6777b538SAndroid Build Coastguard Worker if (chunk_index >= chunks_.size()) // Skip uninitialized chunks.
116*6777b538SAndroid Build Coastguard Worker continue;
117*6777b538SAndroid Build Coastguard Worker chunks_[chunk_index]->EstimateTraceMemoryOverhead(overhead);
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker }
120*6777b538SAndroid Build Coastguard Worker
121*6777b538SAndroid Build Coastguard Worker private:
QueueIsEmpty() const122*6777b538SAndroid Build Coastguard Worker bool QueueIsEmpty() const { return queue_head_ == queue_tail_; }
123*6777b538SAndroid Build Coastguard Worker
QueueSize() const124*6777b538SAndroid Build Coastguard Worker size_t QueueSize() const {
125*6777b538SAndroid Build Coastguard Worker return queue_tail_ > queue_head_
126*6777b538SAndroid Build Coastguard Worker ? queue_tail_ - queue_head_
127*6777b538SAndroid Build Coastguard Worker : queue_tail_ + queue_capacity() - queue_head_;
128*6777b538SAndroid Build Coastguard Worker }
129*6777b538SAndroid Build Coastguard Worker
QueueIsFull() const130*6777b538SAndroid Build Coastguard Worker bool QueueIsFull() const { return QueueSize() == queue_capacity() - 1; }
131*6777b538SAndroid Build Coastguard Worker
queue_capacity() const132*6777b538SAndroid Build Coastguard Worker size_t queue_capacity() const {
133*6777b538SAndroid Build Coastguard Worker // One extra space to help distinguish full state and empty state.
134*6777b538SAndroid Build Coastguard Worker return max_chunks_ + 1;
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker
NextQueueIndex(size_t index) const137*6777b538SAndroid Build Coastguard Worker size_t NextQueueIndex(size_t index) const {
138*6777b538SAndroid Build Coastguard Worker index++;
139*6777b538SAndroid Build Coastguard Worker if (index >= queue_capacity())
140*6777b538SAndroid Build Coastguard Worker index = 0;
141*6777b538SAndroid Build Coastguard Worker return index;
142*6777b538SAndroid Build Coastguard Worker }
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker size_t max_chunks_;
145*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<TraceBufferChunk>> chunks_;
146*6777b538SAndroid Build Coastguard Worker
147*6777b538SAndroid Build Coastguard Worker std::unique_ptr<size_t[]> recyclable_chunks_queue_;
148*6777b538SAndroid Build Coastguard Worker size_t queue_head_;
149*6777b538SAndroid Build Coastguard Worker size_t queue_tail_;
150*6777b538SAndroid Build Coastguard Worker
151*6777b538SAndroid Build Coastguard Worker size_t current_iteration_index_;
152*6777b538SAndroid Build Coastguard Worker uint32_t current_chunk_seq_;
153*6777b538SAndroid Build Coastguard Worker };
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Worker class TraceBufferVector : public TraceBuffer {
156*6777b538SAndroid Build Coastguard Worker public:
TraceBufferVector(size_t max_chunks)157*6777b538SAndroid Build Coastguard Worker TraceBufferVector(size_t max_chunks)
158*6777b538SAndroid Build Coastguard Worker : in_flight_chunk_count_(0),
159*6777b538SAndroid Build Coastguard Worker current_iteration_index_(0),
160*6777b538SAndroid Build Coastguard Worker max_chunks_(max_chunks) {
161*6777b538SAndroid Build Coastguard Worker chunks_.reserve(max_chunks_);
162*6777b538SAndroid Build Coastguard Worker }
163*6777b538SAndroid Build Coastguard Worker
164*6777b538SAndroid Build Coastguard Worker TraceBufferVector(const TraceBufferVector&) = delete;
165*6777b538SAndroid Build Coastguard Worker TraceBufferVector& operator=(const TraceBufferVector&) = delete;
166*6777b538SAndroid Build Coastguard Worker
GetChunk(size_t * index)167*6777b538SAndroid Build Coastguard Worker std::unique_ptr<TraceBufferChunk> GetChunk(size_t* index) override {
168*6777b538SAndroid Build Coastguard Worker HEAP_PROFILER_SCOPED_IGNORE;
169*6777b538SAndroid Build Coastguard Worker
170*6777b538SAndroid Build Coastguard Worker // This function may be called when adding normal events or indirectly from
171*6777b538SAndroid Build Coastguard Worker // AddMetadataEventsWhileLocked(). We can not DECHECK(!IsFull()) because we
172*6777b538SAndroid Build Coastguard Worker // have to add the metadata events and flush thread-local buffers even if
173*6777b538SAndroid Build Coastguard Worker // the buffer is full.
174*6777b538SAndroid Build Coastguard Worker *index = chunks_.size();
175*6777b538SAndroid Build Coastguard Worker // Put nullptr in the slot of a in-flight chunk.
176*6777b538SAndroid Build Coastguard Worker chunks_.push_back(nullptr);
177*6777b538SAndroid Build Coastguard Worker ++in_flight_chunk_count_;
178*6777b538SAndroid Build Coastguard Worker // + 1 because zero chunk_seq is not allowed.
179*6777b538SAndroid Build Coastguard Worker return std::make_unique<TraceBufferChunk>(static_cast<uint32_t>(*index) +
180*6777b538SAndroid Build Coastguard Worker 1);
181*6777b538SAndroid Build Coastguard Worker }
182*6777b538SAndroid Build Coastguard Worker
ReturnChunk(size_t index,std::unique_ptr<TraceBufferChunk> chunk)183*6777b538SAndroid Build Coastguard Worker void ReturnChunk(size_t index,
184*6777b538SAndroid Build Coastguard Worker std::unique_ptr<TraceBufferChunk> chunk) override {
185*6777b538SAndroid Build Coastguard Worker DCHECK_GT(in_flight_chunk_count_, 0u);
186*6777b538SAndroid Build Coastguard Worker DCHECK_LT(index, chunks_.size());
187*6777b538SAndroid Build Coastguard Worker DCHECK(!chunks_[index]);
188*6777b538SAndroid Build Coastguard Worker --in_flight_chunk_count_;
189*6777b538SAndroid Build Coastguard Worker chunks_[index] = std::move(chunk);
190*6777b538SAndroid Build Coastguard Worker }
191*6777b538SAndroid Build Coastguard Worker
IsFull() const192*6777b538SAndroid Build Coastguard Worker bool IsFull() const override { return chunks_.size() >= max_chunks_; }
193*6777b538SAndroid Build Coastguard Worker
Size() const194*6777b538SAndroid Build Coastguard Worker size_t Size() const override {
195*6777b538SAndroid Build Coastguard Worker // This is approximate because not all of the chunks are full.
196*6777b538SAndroid Build Coastguard Worker return chunks_.size() * TraceBufferChunk::kTraceBufferChunkSize;
197*6777b538SAndroid Build Coastguard Worker }
198*6777b538SAndroid Build Coastguard Worker
Capacity() const199*6777b538SAndroid Build Coastguard Worker size_t Capacity() const override {
200*6777b538SAndroid Build Coastguard Worker return max_chunks_ * TraceBufferChunk::kTraceBufferChunkSize;
201*6777b538SAndroid Build Coastguard Worker }
202*6777b538SAndroid Build Coastguard Worker
GetEventByHandle(TraceEventHandle handle)203*6777b538SAndroid Build Coastguard Worker TraceEvent* GetEventByHandle(TraceEventHandle handle) override {
204*6777b538SAndroid Build Coastguard Worker if (handle.chunk_index >= chunks_.size())
205*6777b538SAndroid Build Coastguard Worker return nullptr;
206*6777b538SAndroid Build Coastguard Worker TraceBufferChunk* chunk = chunks_[handle.chunk_index].get();
207*6777b538SAndroid Build Coastguard Worker if (!chunk || chunk->seq() != handle.chunk_seq)
208*6777b538SAndroid Build Coastguard Worker return nullptr;
209*6777b538SAndroid Build Coastguard Worker return chunk->GetEventAt(handle.event_index);
210*6777b538SAndroid Build Coastguard Worker }
211*6777b538SAndroid Build Coastguard Worker
NextChunk()212*6777b538SAndroid Build Coastguard Worker const TraceBufferChunk* NextChunk() override {
213*6777b538SAndroid Build Coastguard Worker while (current_iteration_index_ < chunks_.size()) {
214*6777b538SAndroid Build Coastguard Worker // Skip in-flight chunks.
215*6777b538SAndroid Build Coastguard Worker const TraceBufferChunk* chunk = chunks_[current_iteration_index_++].get();
216*6777b538SAndroid Build Coastguard Worker if (chunk)
217*6777b538SAndroid Build Coastguard Worker return chunk;
218*6777b538SAndroid Build Coastguard Worker }
219*6777b538SAndroid Build Coastguard Worker return nullptr;
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker
EstimateTraceMemoryOverhead(TraceEventMemoryOverhead * overhead)222*6777b538SAndroid Build Coastguard Worker void EstimateTraceMemoryOverhead(
223*6777b538SAndroid Build Coastguard Worker TraceEventMemoryOverhead* overhead) override {
224*6777b538SAndroid Build Coastguard Worker const size_t chunks_ptr_vector_allocated_size =
225*6777b538SAndroid Build Coastguard Worker sizeof(*this) + max_chunks_ * sizeof(decltype(chunks_)::value_type);
226*6777b538SAndroid Build Coastguard Worker const size_t chunks_ptr_vector_resident_size =
227*6777b538SAndroid Build Coastguard Worker sizeof(*this) + chunks_.size() * sizeof(decltype(chunks_)::value_type);
228*6777b538SAndroid Build Coastguard Worker overhead->Add(TraceEventMemoryOverhead::kTraceBuffer,
229*6777b538SAndroid Build Coastguard Worker chunks_ptr_vector_allocated_size,
230*6777b538SAndroid Build Coastguard Worker chunks_ptr_vector_resident_size);
231*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < chunks_.size(); ++i) {
232*6777b538SAndroid Build Coastguard Worker TraceBufferChunk* chunk = chunks_[i].get();
233*6777b538SAndroid Build Coastguard Worker // Skip the in-flight (nullptr) chunks. They will be accounted by the
234*6777b538SAndroid Build Coastguard Worker // per-thread-local dumpers, see ThreadLocalEventBuffer::OnMemoryDump.
235*6777b538SAndroid Build Coastguard Worker if (chunk)
236*6777b538SAndroid Build Coastguard Worker chunk->EstimateTraceMemoryOverhead(overhead);
237*6777b538SAndroid Build Coastguard Worker }
238*6777b538SAndroid Build Coastguard Worker }
239*6777b538SAndroid Build Coastguard Worker
240*6777b538SAndroid Build Coastguard Worker private:
241*6777b538SAndroid Build Coastguard Worker size_t in_flight_chunk_count_;
242*6777b538SAndroid Build Coastguard Worker size_t current_iteration_index_;
243*6777b538SAndroid Build Coastguard Worker size_t max_chunks_;
244*6777b538SAndroid Build Coastguard Worker std::vector<std::unique_ptr<TraceBufferChunk>> chunks_;
245*6777b538SAndroid Build Coastguard Worker };
246*6777b538SAndroid Build Coastguard Worker
247*6777b538SAndroid Build Coastguard Worker } // namespace
248*6777b538SAndroid Build Coastguard Worker
TraceBufferChunk(uint32_t seq)249*6777b538SAndroid Build Coastguard Worker TraceBufferChunk::TraceBufferChunk(uint32_t seq) : next_free_(0), seq_(seq) {}
250*6777b538SAndroid Build Coastguard Worker
251*6777b538SAndroid Build Coastguard Worker TraceBufferChunk::~TraceBufferChunk() = default;
252*6777b538SAndroid Build Coastguard Worker
Reset(uint32_t new_seq)253*6777b538SAndroid Build Coastguard Worker void TraceBufferChunk::Reset(uint32_t new_seq) {
254*6777b538SAndroid Build Coastguard Worker for (size_t i = 0; i < next_free_; ++i)
255*6777b538SAndroid Build Coastguard Worker chunk_[i].Reset();
256*6777b538SAndroid Build Coastguard Worker next_free_ = 0;
257*6777b538SAndroid Build Coastguard Worker seq_ = new_seq;
258*6777b538SAndroid Build Coastguard Worker cached_overhead_estimate_.reset();
259*6777b538SAndroid Build Coastguard Worker }
260*6777b538SAndroid Build Coastguard Worker
AddTraceEvent(size_t * event_index)261*6777b538SAndroid Build Coastguard Worker TraceEvent* TraceBufferChunk::AddTraceEvent(size_t* event_index) {
262*6777b538SAndroid Build Coastguard Worker DCHECK(!IsFull());
263*6777b538SAndroid Build Coastguard Worker *event_index = next_free_++;
264*6777b538SAndroid Build Coastguard Worker return &chunk_[*event_index];
265*6777b538SAndroid Build Coastguard Worker }
266*6777b538SAndroid Build Coastguard Worker
EstimateTraceMemoryOverhead(TraceEventMemoryOverhead * overhead)267*6777b538SAndroid Build Coastguard Worker void TraceBufferChunk::EstimateTraceMemoryOverhead(
268*6777b538SAndroid Build Coastguard Worker TraceEventMemoryOverhead* overhead) {
269*6777b538SAndroid Build Coastguard Worker if (!cached_overhead_estimate_) {
270*6777b538SAndroid Build Coastguard Worker cached_overhead_estimate_ = std::make_unique<TraceEventMemoryOverhead>();
271*6777b538SAndroid Build Coastguard Worker
272*6777b538SAndroid Build Coastguard Worker // When estimating the size of TraceBufferChunk, exclude the array of trace
273*6777b538SAndroid Build Coastguard Worker // events, as they are computed individually below.
274*6777b538SAndroid Build Coastguard Worker cached_overhead_estimate_->Add(TraceEventMemoryOverhead::kTraceBufferChunk,
275*6777b538SAndroid Build Coastguard Worker sizeof(*this) - sizeof(chunk_));
276*6777b538SAndroid Build Coastguard Worker }
277*6777b538SAndroid Build Coastguard Worker
278*6777b538SAndroid Build Coastguard Worker const size_t num_cached_estimated_events =
279*6777b538SAndroid Build Coastguard Worker cached_overhead_estimate_->GetCount(
280*6777b538SAndroid Build Coastguard Worker TraceEventMemoryOverhead::kTraceEvent);
281*6777b538SAndroid Build Coastguard Worker DCHECK_LE(num_cached_estimated_events, size());
282*6777b538SAndroid Build Coastguard Worker
283*6777b538SAndroid Build Coastguard Worker if (IsFull() && num_cached_estimated_events == size()) {
284*6777b538SAndroid Build Coastguard Worker overhead->Update(*cached_overhead_estimate_);
285*6777b538SAndroid Build Coastguard Worker return;
286*6777b538SAndroid Build Coastguard Worker }
287*6777b538SAndroid Build Coastguard Worker
288*6777b538SAndroid Build Coastguard Worker for (size_t i = num_cached_estimated_events; i < size(); ++i)
289*6777b538SAndroid Build Coastguard Worker chunk_[i].EstimateTraceMemoryOverhead(cached_overhead_estimate_.get());
290*6777b538SAndroid Build Coastguard Worker
291*6777b538SAndroid Build Coastguard Worker if (IsFull()) {
292*6777b538SAndroid Build Coastguard Worker cached_overhead_estimate_->AddSelf();
293*6777b538SAndroid Build Coastguard Worker } else {
294*6777b538SAndroid Build Coastguard Worker // The unused TraceEvents in |chunks_| are not cached. They will keep
295*6777b538SAndroid Build Coastguard Worker // changing as new TraceEvents are added to this chunk, so they are
296*6777b538SAndroid Build Coastguard Worker // computed on the fly.
297*6777b538SAndroid Build Coastguard Worker const size_t num_unused_trace_events = capacity() - size();
298*6777b538SAndroid Build Coastguard Worker overhead->Add(TraceEventMemoryOverhead::kUnusedTraceEvent,
299*6777b538SAndroid Build Coastguard Worker num_unused_trace_events * sizeof(TraceEvent));
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker
302*6777b538SAndroid Build Coastguard Worker overhead->Update(*cached_overhead_estimate_);
303*6777b538SAndroid Build Coastguard Worker }
304*6777b538SAndroid Build Coastguard Worker
305*6777b538SAndroid Build Coastguard Worker TraceResultBuffer::OutputCallback
GetCallback()306*6777b538SAndroid Build Coastguard Worker TraceResultBuffer::SimpleOutput::GetCallback() {
307*6777b538SAndroid Build Coastguard Worker return BindRepeating(&SimpleOutput::Append, Unretained(this));
308*6777b538SAndroid Build Coastguard Worker }
309*6777b538SAndroid Build Coastguard Worker
Append(const std::string & json_trace_output)310*6777b538SAndroid Build Coastguard Worker void TraceResultBuffer::SimpleOutput::Append(
311*6777b538SAndroid Build Coastguard Worker const std::string& json_trace_output) {
312*6777b538SAndroid Build Coastguard Worker json_output += json_trace_output;
313*6777b538SAndroid Build Coastguard Worker }
314*6777b538SAndroid Build Coastguard Worker
TraceResultBuffer()315*6777b538SAndroid Build Coastguard Worker TraceResultBuffer::TraceResultBuffer() : append_comma_(false) {}
316*6777b538SAndroid Build Coastguard Worker
317*6777b538SAndroid Build Coastguard Worker TraceResultBuffer::~TraceResultBuffer() = default;
318*6777b538SAndroid Build Coastguard Worker
SetOutputCallback(OutputCallback json_chunk_callback)319*6777b538SAndroid Build Coastguard Worker void TraceResultBuffer::SetOutputCallback(OutputCallback json_chunk_callback) {
320*6777b538SAndroid Build Coastguard Worker output_callback_ = std::move(json_chunk_callback);
321*6777b538SAndroid Build Coastguard Worker }
322*6777b538SAndroid Build Coastguard Worker
Start()323*6777b538SAndroid Build Coastguard Worker void TraceResultBuffer::Start() {
324*6777b538SAndroid Build Coastguard Worker append_comma_ = false;
325*6777b538SAndroid Build Coastguard Worker output_callback_.Run("[");
326*6777b538SAndroid Build Coastguard Worker }
327*6777b538SAndroid Build Coastguard Worker
AddFragment(const std::string & trace_fragment)328*6777b538SAndroid Build Coastguard Worker void TraceResultBuffer::AddFragment(const std::string& trace_fragment) {
329*6777b538SAndroid Build Coastguard Worker if (append_comma_)
330*6777b538SAndroid Build Coastguard Worker output_callback_.Run(",");
331*6777b538SAndroid Build Coastguard Worker append_comma_ = true;
332*6777b538SAndroid Build Coastguard Worker output_callback_.Run(trace_fragment);
333*6777b538SAndroid Build Coastguard Worker }
334*6777b538SAndroid Build Coastguard Worker
Finish()335*6777b538SAndroid Build Coastguard Worker void TraceResultBuffer::Finish() {
336*6777b538SAndroid Build Coastguard Worker output_callback_.Run("]");
337*6777b538SAndroid Build Coastguard Worker }
338*6777b538SAndroid Build Coastguard Worker
CreateTraceBufferRingBuffer(size_t max_chunks)339*6777b538SAndroid Build Coastguard Worker TraceBuffer* TraceBuffer::CreateTraceBufferRingBuffer(size_t max_chunks) {
340*6777b538SAndroid Build Coastguard Worker return new TraceBufferRingBuffer(max_chunks);
341*6777b538SAndroid Build Coastguard Worker }
342*6777b538SAndroid Build Coastguard Worker
CreateTraceBufferVectorOfSize(size_t max_chunks)343*6777b538SAndroid Build Coastguard Worker TraceBuffer* TraceBuffer::CreateTraceBufferVectorOfSize(size_t max_chunks) {
344*6777b538SAndroid Build Coastguard Worker return new TraceBufferVector(max_chunks);
345*6777b538SAndroid Build Coastguard Worker }
346*6777b538SAndroid Build Coastguard Worker
347*6777b538SAndroid Build Coastguard Worker } // namespace trace_event
348*6777b538SAndroid Build Coastguard Worker } // namespace base
349