Home | History | Annotate | Download | only in trace_processor
      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