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