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> 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 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 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 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 68 TraceStorage::~TraceStorage() {} 69 70 void TraceStorage::ResetStorage() { 71 *this = TraceStorage(); 72 } 73 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 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 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 114 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