1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "src/trace_processor/trace_storage.h"
18 
19 #include <string.h>
20 #include <algorithm>
21 #include <limits>
22 
23 #include "perfetto/base/no_destructor.h"
24 
25 namespace perfetto {
26 namespace trace_processor {
27 
28 namespace {
29 
30 template <typename T>
MaybeUpdateMinMax(T begin_it,T end_it,int64_t * min_value,int64_t * max_value)31 void MaybeUpdateMinMax(T begin_it,
32                        T end_it,
33                        int64_t* min_value,
34                        int64_t* max_value) {
35   if (begin_it == end_it) {
36     return;
37   }
38   std::pair<T, T> minmax = std::minmax_element(begin_it, end_it);
39   *min_value = std::min(*min_value, *minmax.first);
40   *max_value = std::max(*max_value, *minmax.second);
41 }
42 
CreateRefTypeStringMap()43 std::vector<const char*> CreateRefTypeStringMap() {
44   std::vector<const char*> map(RefType::kRefMax);
45   map[RefType::kRefNoRef] = nullptr;
46   map[RefType::kRefUtid] = "utid";
47   map[RefType::kRefCpuId] = "cpu";
48   map[RefType::kRefIrq] = "irq";
49   map[RefType::kRefSoftIrq] = "softirq";
50   map[RefType::kRefUpid] = "upid";
51   return map;
52 }
53 
54 }  // namespace
55 
GetRefTypeStringMap()56 const std::vector<const char*>& GetRefTypeStringMap() {
57   static const base::NoDestructor<std::vector<const char*>> map(
58       CreateRefTypeStringMap());
59   return map.ref();
60 }
61 
TraceStorage()62 TraceStorage::TraceStorage() {
63   // Upid/utid 0 is reserved for idle processes/threads.
64   unique_processes_.emplace_back(0);
65   unique_threads_.emplace_back(0);
66 }
67 
~TraceStorage()68 TraceStorage::~TraceStorage() {}
69 
ResetStorage()70 void TraceStorage::ResetStorage() {
71   *this = TraceStorage();
72 }
73 
RecordQueryBegin(const std::string & query,int64_t time_queued,int64_t time_started)74 uint32_t TraceStorage::SqlStats::RecordQueryBegin(const std::string& query,
75                                                   int64_t time_queued,
76                                                   int64_t time_started) {
77   if (queries_.size() >= kMaxLogEntries) {
78     queries_.pop_front();
79     times_queued_.pop_front();
80     times_started_.pop_front();
81     times_first_next_.pop_front();
82     times_ended_.pop_front();
83     popped_queries_++;
84   }
85   queries_.push_back(query);
86   times_queued_.push_back(time_queued);
87   times_started_.push_back(time_started);
88   times_first_next_.push_back(0);
89   times_ended_.push_back(0);
90   return static_cast<uint32_t>(popped_queries_ + queries_.size() - 1);
91 }
92 
RecordQueryFirstNext(uint32_t row,int64_t time_first_next)93 void TraceStorage::SqlStats::RecordQueryFirstNext(uint32_t row,
94                                                   int64_t time_first_next) {
95   // This means we've popped this query off the queue of queries before it had
96   // a chance to finish. Just silently drop this number.
97   if (popped_queries_ > row)
98     return;
99   uint32_t queue_row = row - popped_queries_;
100   PERFETTO_DCHECK(queue_row < queries_.size());
101   times_first_next_[queue_row] = time_first_next;
102 }
103 
RecordQueryEnd(uint32_t row,int64_t time_ended)104 void TraceStorage::SqlStats::RecordQueryEnd(uint32_t row, int64_t time_ended) {
105   // This means we've popped this query off the queue of queries before it had
106   // a chance to finish. Just silently drop this number.
107   if (popped_queries_ > row)
108     return;
109   uint32_t queue_row = row - popped_queries_;
110   PERFETTO_DCHECK(queue_row < queries_.size());
111   times_ended_[queue_row] = time_ended;
112 }
113 
GetTraceTimestampBoundsNs() const114 std::pair<int64_t, int64_t> TraceStorage::GetTraceTimestampBoundsNs() const {
115   int64_t start_ns = std::numeric_limits<int64_t>::max();
116   int64_t end_ns = std::numeric_limits<int64_t>::min();
117   MaybeUpdateMinMax(slices_.start_ns().begin(), slices_.start_ns().end(),
118                     &start_ns, &end_ns);
119   MaybeUpdateMinMax(counter_values_.timestamps().begin(),
120                     counter_values_.timestamps().end(), &start_ns, &end_ns);
121   MaybeUpdateMinMax(instants_.timestamps().begin(),
122                     instants_.timestamps().end(), &start_ns, &end_ns);
123   MaybeUpdateMinMax(nestable_slices_.start_ns().begin(),
124                     nestable_slices_.start_ns().end(), &start_ns, &end_ns);
125   MaybeUpdateMinMax(android_log_.timestamps().begin(),
126                     android_log_.timestamps().end(), &start_ns, &end_ns);
127 
128   if (start_ns == std::numeric_limits<int64_t>::max()) {
129     return std::make_pair(0, 0);
130   }
131   return std::make_pair(start_ns, end_ns);
132 }
133 
134 }  // namespace trace_processor
135 }  // namespace perfetto
136