/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "src/trace_processor/trace_storage.h" #include #include #include #include "perfetto/base/no_destructor.h" namespace perfetto { namespace trace_processor { namespace { template void MaybeUpdateMinMax(T begin_it, T end_it, int64_t* min_value, int64_t* max_value) { if (begin_it == end_it) { return; } std::pair minmax = std::minmax_element(begin_it, end_it); *min_value = std::min(*min_value, *minmax.first); *max_value = std::max(*max_value, *minmax.second); } std::vector CreateRefTypeStringMap() { std::vector map(RefType::kRefMax); map[RefType::kRefNoRef] = nullptr; map[RefType::kRefUtid] = "utid"; map[RefType::kRefCpuId] = "cpu"; map[RefType::kRefIrq] = "irq"; map[RefType::kRefSoftIrq] = "softirq"; map[RefType::kRefUpid] = "upid"; return map; } } // namespace const std::vector& GetRefTypeStringMap() { static const base::NoDestructor> map( CreateRefTypeStringMap()); return map.ref(); } TraceStorage::TraceStorage() { // Upid/utid 0 is reserved for idle processes/threads. unique_processes_.emplace_back(0); unique_threads_.emplace_back(0); } TraceStorage::~TraceStorage() {} void TraceStorage::ResetStorage() { *this = TraceStorage(); } uint32_t TraceStorage::SqlStats::RecordQueryBegin(const std::string& query, int64_t time_queued, int64_t time_started) { if (queries_.size() >= kMaxLogEntries) { queries_.pop_front(); times_queued_.pop_front(); times_started_.pop_front(); times_first_next_.pop_front(); times_ended_.pop_front(); popped_queries_++; } queries_.push_back(query); times_queued_.push_back(time_queued); times_started_.push_back(time_started); times_first_next_.push_back(0); times_ended_.push_back(0); return static_cast(popped_queries_ + queries_.size() - 1); } void TraceStorage::SqlStats::RecordQueryFirstNext(uint32_t row, int64_t time_first_next) { // This means we've popped this query off the queue of queries before it had // a chance to finish. Just silently drop this number. if (popped_queries_ > row) return; uint32_t queue_row = row - popped_queries_; PERFETTO_DCHECK(queue_row < queries_.size()); times_first_next_[queue_row] = time_first_next; } void TraceStorage::SqlStats::RecordQueryEnd(uint32_t row, int64_t time_ended) { // This means we've popped this query off the queue of queries before it had // a chance to finish. Just silently drop this number. if (popped_queries_ > row) return; uint32_t queue_row = row - popped_queries_; PERFETTO_DCHECK(queue_row < queries_.size()); times_ended_[queue_row] = time_ended; } std::pair TraceStorage::GetTraceTimestampBoundsNs() const { int64_t start_ns = std::numeric_limits::max(); int64_t end_ns = std::numeric_limits::min(); MaybeUpdateMinMax(slices_.start_ns().begin(), slices_.start_ns().end(), &start_ns, &end_ns); MaybeUpdateMinMax(counter_values_.timestamps().begin(), counter_values_.timestamps().end(), &start_ns, &end_ns); MaybeUpdateMinMax(instants_.timestamps().begin(), instants_.timestamps().end(), &start_ns, &end_ns); MaybeUpdateMinMax(nestable_slices_.start_ns().begin(), nestable_slices_.start_ns().end(), &start_ns, &end_ns); MaybeUpdateMinMax(android_log_.timestamps().begin(), android_log_.timestamps().end(), &start_ns, &end_ns); if (start_ns == std::numeric_limits::max()) { return std::make_pair(0, 0); } return std::make_pair(start_ns, end_ns); } } // namespace trace_processor } // namespace perfetto