xref: /aosp_15_r20/external/cronet/base/trace_event/trace_buffer.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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