Home | History | Annotate | Download | only in trace_processor
      1 /*
      2  * Copyright (C) 2017 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 #ifndef SRC_TRACE_PROCESSOR_TRACE_STORAGE_H_
     18 #define SRC_TRACE_PROCESSOR_TRACE_STORAGE_H_
     19 
     20 #include <array>
     21 #include <deque>
     22 #include <map>
     23 #include <string>
     24 #include <unordered_map>
     25 #include <utility>
     26 #include <vector>
     27 
     28 #include "perfetto/base/hash.h"
     29 #include "perfetto/base/logging.h"
     30 #include "perfetto/base/optional.h"
     31 #include "perfetto/base/string_view.h"
     32 #include "perfetto/base/time.h"
     33 #include "perfetto/base/utils.h"
     34 #include "src/trace_processor/ftrace_utils.h"
     35 #include "src/trace_processor/stats.h"
     36 #include "src/trace_processor/string_pool.h"
     37 
     38 namespace perfetto {
     39 namespace trace_processor {
     40 
     41 // UniquePid is an offset into |unique_processes_|. This is necessary because
     42 // Unix pids are reused and thus not guaranteed to be unique over a long
     43 // period of time.
     44 using UniquePid = uint32_t;
     45 
     46 // UniqueTid is an offset into |unique_threads_|. Necessary because tids can
     47 // be reused.
     48 using UniqueTid = uint32_t;
     49 
     50 // StringId is an offset into |string_pool_|.
     51 using StringId = StringPool::Id;
     52 
     53 // Identifiers for all the tables in the database.
     54 enum TableId : uint8_t {
     55   // Intentionally don't have TableId == 0 so that RowId == 0 can refer to an
     56   // invalid row id.
     57   kCounterValues = 1,
     58   kRawEvents = 2,
     59   kInstants = 3,
     60   kSched = 4,
     61 };
     62 
     63 // The top 8 bits are set to the TableId and the bottom 32 to the row of the
     64 // table.
     65 using RowId = int64_t;
     66 static const RowId kInvalidRowId = 0;
     67 
     68 using ArgSetId = uint32_t;
     69 static const ArgSetId kInvalidArgSetId = 0;
     70 
     71 enum RefType {
     72   kRefNoRef = 0,
     73   kRefUtid = 1,
     74   kRefCpuId = 2,
     75   kRefIrq = 3,
     76   kRefSoftIrq = 4,
     77   kRefUpid = 5,
     78   kRefMax
     79 };
     80 
     81 const std::vector<const char*>& GetRefTypeStringMap();
     82 
     83 // Stores a data inside a trace file in a columnar form. This makes it efficient
     84 // to read or search across a single field of the trace (e.g. all the thread
     85 // names for a given CPU).
     86 class TraceStorage {
     87  public:
     88   TraceStorage();
     89 
     90   virtual ~TraceStorage();
     91 
     92   // Information about a unique process seen in a trace.
     93   struct Process {
     94     explicit Process(uint32_t p) : pid(p) {}
     95     int64_t start_ns = 0;
     96     StringId name_id = 0;
     97     uint32_t pid = 0;
     98     base::Optional<UniquePid> pupid;
     99   };
    100 
    101   // Information about a unique thread seen in a trace.
    102   struct Thread {
    103     explicit Thread(uint32_t t) : tid(t) {}
    104     int64_t start_ns = 0;
    105     StringId name_id = 0;
    106     base::Optional<UniquePid> upid;
    107     uint32_t tid = 0;
    108   };
    109 
    110   // Generic key value storage which can be referenced by other tables.
    111   class Args {
    112    public:
    113     // Variadic type representing the possible values for the args table.
    114     struct Variadic {
    115       enum Type { kInt, kString, kReal };
    116 
    117       static Variadic Integer(int64_t int_value) {
    118         Variadic variadic;
    119         variadic.type = Type::kInt;
    120         variadic.int_value = int_value;
    121         return variadic;
    122       }
    123 
    124       static Variadic String(StringId string_id) {
    125         Variadic variadic;
    126         variadic.type = Type::kString;
    127         variadic.string_value = string_id;
    128         return variadic;
    129       }
    130 
    131       static Variadic Real(double real_value) {
    132         Variadic variadic;
    133         variadic.type = Type::kReal;
    134         variadic.real_value = real_value;
    135         return variadic;
    136       }
    137 
    138       Type type;
    139       union {
    140         int64_t int_value;
    141         StringId string_value;
    142         double real_value;
    143       };
    144     };
    145 
    146     struct Arg {
    147       StringId flat_key = 0;
    148       StringId key = 0;
    149       Variadic value = Variadic::Integer(0);
    150 
    151       // This is only used by the arg tracker and so is not part of the hash.
    152       RowId row_id = 0;
    153     };
    154 
    155     struct ArgHasher {
    156       uint64_t operator()(const Arg& arg) const noexcept {
    157         base::Hash hash;
    158         hash.Update(arg.key);
    159         // We don't hash arg.flat_key because it's a subsequence of arg.key.
    160         switch (arg.value.type) {
    161           case Variadic::Type::kInt:
    162             hash.Update(arg.value.int_value);
    163             break;
    164           case Variadic::Type::kString:
    165             hash.Update(arg.value.string_value);
    166             break;
    167           case Variadic::Type::kReal:
    168             hash.Update(arg.value.real_value);
    169             break;
    170         }
    171         return hash.digest();
    172       }
    173     };
    174 
    175     const std::deque<ArgSetId>& set_ids() const { return set_ids_; }
    176     const std::deque<StringId>& flat_keys() const { return flat_keys_; }
    177     const std::deque<StringId>& keys() const { return keys_; }
    178     const std::deque<Variadic>& arg_values() const { return arg_values_; }
    179     uint32_t args_count() const {
    180       return static_cast<uint32_t>(set_ids_.size());
    181     }
    182 
    183     ArgSetId AddArgSet(const std::vector<Arg>& args,
    184                        uint32_t begin,
    185                        uint32_t end) {
    186       base::Hash hash;
    187       for (uint32_t i = begin; i < end; i++) {
    188         hash.Update(ArgHasher()(args[i]));
    189       }
    190 
    191       ArgSetHash digest = hash.digest();
    192       auto it = arg_row_for_hash_.find(digest);
    193       if (it != arg_row_for_hash_.end()) {
    194         return set_ids_[it->second];
    195       }
    196 
    197       // The +1 ensures that nothing has an id == kInvalidArgSetId == 0.
    198       ArgSetId id = static_cast<uint32_t>(arg_row_for_hash_.size()) + 1;
    199       arg_row_for_hash_.emplace(digest, args_count());
    200       for (uint32_t i = begin; i < end; i++) {
    201         const auto& arg = args[i];
    202         set_ids_.emplace_back(id);
    203         flat_keys_.emplace_back(arg.flat_key);
    204         keys_.emplace_back(arg.key);
    205         arg_values_.emplace_back(arg.value);
    206       }
    207       return id;
    208     }
    209 
    210    private:
    211     using ArgSetHash = uint64_t;
    212 
    213     std::deque<ArgSetId> set_ids_;
    214     std::deque<StringId> flat_keys_;
    215     std::deque<StringId> keys_;
    216     std::deque<Variadic> arg_values_;
    217 
    218     std::unordered_map<ArgSetHash, uint32_t> arg_row_for_hash_;
    219   };
    220 
    221   class Slices {
    222    public:
    223     inline size_t AddSlice(uint32_t cpu,
    224                            int64_t start_ns,
    225                            int64_t duration_ns,
    226                            UniqueTid utid,
    227                            ftrace_utils::TaskState end_state,
    228                            int32_t priority) {
    229       cpus_.emplace_back(cpu);
    230       start_ns_.emplace_back(start_ns);
    231       durations_.emplace_back(duration_ns);
    232       utids_.emplace_back(utid);
    233       end_states_.emplace_back(end_state);
    234       priorities_.emplace_back(priority);
    235 
    236       if (utid >= rows_for_utids_.size())
    237         rows_for_utids_.resize(utid + 1);
    238       rows_for_utids_[utid].emplace_back(slice_count() - 1);
    239       return slice_count() - 1;
    240     }
    241 
    242     void set_duration(size_t index, int64_t duration_ns) {
    243       durations_[index] = duration_ns;
    244     }
    245 
    246     void set_end_state(size_t index, ftrace_utils::TaskState end_state) {
    247       end_states_[index] = end_state;
    248     }
    249 
    250     size_t slice_count() const { return start_ns_.size(); }
    251 
    252     const std::deque<uint32_t>& cpus() const { return cpus_; }
    253 
    254     const std::deque<int64_t>& start_ns() const { return start_ns_; }
    255 
    256     const std::deque<int64_t>& durations() const { return durations_; }
    257 
    258     const std::deque<UniqueTid>& utids() const { return utids_; }
    259 
    260     const std::deque<ftrace_utils::TaskState>& end_state() const {
    261       return end_states_;
    262     }
    263 
    264     const std::deque<int32_t>& priorities() const { return priorities_; }
    265 
    266     const std::deque<std::vector<uint32_t>>& rows_for_utids() const {
    267       return rows_for_utids_;
    268     }
    269 
    270    private:
    271     // Each deque below has the same number of entries (the number of slices
    272     // in the trace for the CPU).
    273     std::deque<uint32_t> cpus_;
    274     std::deque<int64_t> start_ns_;
    275     std::deque<int64_t> durations_;
    276     std::deque<UniqueTid> utids_;
    277     std::deque<ftrace_utils::TaskState> end_states_;
    278     std::deque<int32_t> priorities_;
    279 
    280     // One row per utid.
    281     std::deque<std::vector<uint32_t>> rows_for_utids_;
    282   };
    283 
    284   class NestableSlices {
    285    public:
    286     inline size_t AddSlice(int64_t start_ns,
    287                            int64_t duration_ns,
    288                            int64_t ref,
    289                            RefType type,
    290                            StringId cat,
    291                            StringId name,
    292                            uint8_t depth,
    293                            int64_t stack_id,
    294                            int64_t parent_stack_id) {
    295       start_ns_.emplace_back(start_ns);
    296       durations_.emplace_back(duration_ns);
    297       refs_.emplace_back(ref);
    298       types_.emplace_back(type);
    299       cats_.emplace_back(cat);
    300       names_.emplace_back(name);
    301       depths_.emplace_back(depth);
    302       stack_ids_.emplace_back(stack_id);
    303       parent_stack_ids_.emplace_back(parent_stack_id);
    304       return slice_count() - 1;
    305     }
    306 
    307     void set_duration(size_t index, int64_t duration_ns) {
    308       durations_[index] = duration_ns;
    309     }
    310 
    311     void set_stack_id(size_t index, int64_t stack_id) {
    312       stack_ids_[index] = stack_id;
    313     }
    314 
    315     size_t slice_count() const { return start_ns_.size(); }
    316     const std::deque<int64_t>& start_ns() const { return start_ns_; }
    317     const std::deque<int64_t>& durations() const { return durations_; }
    318     const std::deque<int64_t>& refs() const { return refs_; }
    319     const std::deque<RefType>& types() const { return types_; }
    320     const std::deque<StringId>& cats() const { return cats_; }
    321     const std::deque<StringId>& names() const { return names_; }
    322     const std::deque<uint8_t>& depths() const { return depths_; }
    323     const std::deque<int64_t>& stack_ids() const { return stack_ids_; }
    324     const std::deque<int64_t>& parent_stack_ids() const {
    325       return parent_stack_ids_;
    326     }
    327 
    328    private:
    329     std::deque<int64_t> start_ns_;
    330     std::deque<int64_t> durations_;
    331     std::deque<int64_t> refs_;
    332     std::deque<RefType> types_;
    333     std::deque<StringId> cats_;
    334     std::deque<StringId> names_;
    335     std::deque<uint8_t> depths_;
    336     std::deque<int64_t> stack_ids_;
    337     std::deque<int64_t> parent_stack_ids_;
    338   };
    339 
    340   class CounterDefinitions {
    341    public:
    342     using Id = uint32_t;
    343     static constexpr Id kInvalidId = std::numeric_limits<Id>::max();
    344 
    345     inline Id AddCounterDefinition(StringId name_id,
    346                                    int64_t ref,
    347                                    RefType type) {
    348       base::Hash hash;
    349       hash.Update(name_id);
    350       hash.Update(ref);
    351       hash.Update(type);
    352 
    353       // TODO(lalitm): this is a perf bottleneck and likely we can do something
    354       // quite a bit better here.
    355       uint64_t digest = hash.digest();
    356       auto it = hash_to_row_idx_.find(digest);
    357       if (it != hash_to_row_idx_.end())
    358         return it->second;
    359 
    360       name_ids_.emplace_back(name_id);
    361       refs_.emplace_back(ref);
    362       types_.emplace_back(type);
    363       hash_to_row_idx_.emplace(digest, size() - 1);
    364       return size() - 1;
    365     }
    366 
    367     uint32_t size() const { return static_cast<uint32_t>(name_ids_.size()); }
    368 
    369     const std::deque<StringId>& name_ids() const { return name_ids_; }
    370 
    371     const std::deque<int64_t>& refs() const { return refs_; }
    372 
    373     const std::deque<RefType>& types() const { return types_; }
    374 
    375    private:
    376     std::deque<StringId> name_ids_;
    377     std::deque<int64_t> refs_;
    378     std::deque<RefType> types_;
    379 
    380     std::unordered_map<uint64_t, uint32_t> hash_to_row_idx_;
    381   };
    382 
    383   class CounterValues {
    384    public:
    385     inline uint32_t AddCounterValue(CounterDefinitions::Id counter_id,
    386                                     int64_t timestamp,
    387                                     double value) {
    388       counter_ids_.emplace_back(counter_id);
    389       timestamps_.emplace_back(timestamp);
    390       values_.emplace_back(value);
    391       arg_set_ids_.emplace_back(kInvalidArgSetId);
    392 
    393       if (counter_id != CounterDefinitions::kInvalidId) {
    394         if (counter_id >= rows_for_counter_id_.size()) {
    395           rows_for_counter_id_.resize(counter_id + 1);
    396         }
    397         rows_for_counter_id_[counter_id].emplace_back(size() - 1);
    398       }
    399       return size() - 1;
    400     }
    401 
    402     void set_counter_id(uint32_t index, CounterDefinitions::Id counter_id) {
    403       PERFETTO_DCHECK(counter_ids_[index] == CounterDefinitions::kInvalidId);
    404 
    405       counter_ids_[index] = counter_id;
    406       if (counter_id >= rows_for_counter_id_.size()) {
    407         rows_for_counter_id_.resize(counter_id + 1);
    408       }
    409 
    410       auto* new_rows = &rows_for_counter_id_[counter_id];
    411       new_rows->insert(
    412           std::upper_bound(new_rows->begin(), new_rows->end(), index), index);
    413     }
    414 
    415     void set_arg_set_id(uint32_t row, ArgSetId id) { arg_set_ids_[row] = id; }
    416 
    417     uint32_t size() const { return static_cast<uint32_t>(counter_ids_.size()); }
    418 
    419     const std::deque<CounterDefinitions::Id>& counter_ids() const {
    420       return counter_ids_;
    421     }
    422 
    423     const std::deque<int64_t>& timestamps() const { return timestamps_; }
    424 
    425     const std::deque<double>& values() const { return values_; }
    426 
    427     const std::deque<ArgSetId>& arg_set_ids() const { return arg_set_ids_; }
    428 
    429     const std::deque<std::vector<uint32_t>>& rows_for_counter_id() const {
    430       return rows_for_counter_id_;
    431     }
    432 
    433    private:
    434     std::deque<CounterDefinitions::Id> counter_ids_;
    435     std::deque<int64_t> timestamps_;
    436     std::deque<double> values_;
    437     std::deque<ArgSetId> arg_set_ids_;
    438 
    439     // Indexed by counter_id value and contains the row numbers corresponding to
    440     // it.
    441     std::deque<std::vector<uint32_t>> rows_for_counter_id_;
    442   };
    443 
    444   class SqlStats {
    445    public:
    446     static constexpr size_t kMaxLogEntries = 100;
    447     uint32_t RecordQueryBegin(const std::string& query,
    448                               int64_t time_queued,
    449                               int64_t time_started);
    450     void RecordQueryFirstNext(uint32_t row, int64_t time_first_next);
    451     void RecordQueryEnd(uint32_t row, int64_t time_end);
    452     size_t size() const { return queries_.size(); }
    453     const std::deque<std::string>& queries() const { return queries_; }
    454     const std::deque<int64_t>& times_queued() const { return times_queued_; }
    455     const std::deque<int64_t>& times_started() const { return times_started_; }
    456     const std::deque<int64_t>& times_first_next() const {
    457       return times_first_next_;
    458     }
    459     const std::deque<int64_t>& times_ended() const { return times_ended_; }
    460 
    461    private:
    462     uint32_t popped_queries_ = 0;
    463 
    464     std::deque<std::string> queries_;
    465     std::deque<int64_t> times_queued_;
    466     std::deque<int64_t> times_started_;
    467     std::deque<int64_t> times_first_next_;
    468     std::deque<int64_t> times_ended_;
    469   };
    470 
    471   class Instants {
    472    public:
    473     inline uint32_t AddInstantEvent(int64_t timestamp,
    474                                     StringId name_id,
    475                                     double value,
    476                                     int64_t ref,
    477                                     RefType type) {
    478       timestamps_.emplace_back(timestamp);
    479       name_ids_.emplace_back(name_id);
    480       values_.emplace_back(value);
    481       refs_.emplace_back(ref);
    482       types_.emplace_back(type);
    483       arg_set_ids_.emplace_back(kInvalidArgSetId);
    484       return static_cast<uint32_t>(instant_count() - 1);
    485     }
    486 
    487     void set_ref(uint32_t row, int64_t ref) { refs_[row] = ref; }
    488 
    489     void set_arg_set_id(uint32_t row, ArgSetId id) { arg_set_ids_[row] = id; }
    490 
    491     size_t instant_count() const { return timestamps_.size(); }
    492 
    493     const std::deque<int64_t>& timestamps() const { return timestamps_; }
    494 
    495     const std::deque<StringId>& name_ids() const { return name_ids_; }
    496 
    497     const std::deque<double>& values() const { return values_; }
    498 
    499     const std::deque<int64_t>& refs() const { return refs_; }
    500 
    501     const std::deque<RefType>& types() const { return types_; }
    502 
    503     const std::deque<ArgSetId>& arg_set_ids() const { return arg_set_ids_; }
    504 
    505    private:
    506     std::deque<int64_t> timestamps_;
    507     std::deque<StringId> name_ids_;
    508     std::deque<double> values_;
    509     std::deque<int64_t> refs_;
    510     std::deque<RefType> types_;
    511     std::deque<ArgSetId> arg_set_ids_;
    512   };
    513 
    514   class RawEvents {
    515    public:
    516     inline RowId AddRawEvent(int64_t timestamp,
    517                              StringId name_id,
    518                              uint32_t cpu,
    519                              UniqueTid utid) {
    520       timestamps_.emplace_back(timestamp);
    521       name_ids_.emplace_back(name_id);
    522       cpus_.emplace_back(cpu);
    523       utids_.emplace_back(utid);
    524       arg_set_ids_.emplace_back(kInvalidArgSetId);
    525       return CreateRowId(TableId::kRawEvents,
    526                          static_cast<uint32_t>(raw_event_count() - 1));
    527     }
    528 
    529     void set_arg_set_id(uint32_t row, ArgSetId id) { arg_set_ids_[row] = id; }
    530 
    531     size_t raw_event_count() const { return timestamps_.size(); }
    532 
    533     const std::deque<int64_t>& timestamps() const { return timestamps_; }
    534 
    535     const std::deque<StringId>& name_ids() const { return name_ids_; }
    536 
    537     const std::deque<uint32_t>& cpus() const { return cpus_; }
    538 
    539     const std::deque<UniqueTid>& utids() const { return utids_; }
    540 
    541     const std::deque<ArgSetId>& arg_set_ids() const { return arg_set_ids_; }
    542 
    543    private:
    544     std::deque<int64_t> timestamps_;
    545     std::deque<StringId> name_ids_;
    546     std::deque<uint32_t> cpus_;
    547     std::deque<UniqueTid> utids_;
    548     std::deque<ArgSetId> arg_set_ids_;
    549   };
    550 
    551   class AndroidLogs {
    552    public:
    553     inline size_t AddLogEvent(int64_t timestamp,
    554                               UniqueTid utid,
    555                               uint8_t prio,
    556                               StringId tag_id,
    557                               StringId msg_id) {
    558       timestamps_.emplace_back(timestamp);
    559       utids_.emplace_back(utid);
    560       prios_.emplace_back(prio);
    561       tag_ids_.emplace_back(tag_id);
    562       msg_ids_.emplace_back(msg_id);
    563       return size() - 1;
    564     }
    565 
    566     size_t size() const { return timestamps_.size(); }
    567 
    568     const std::deque<int64_t>& timestamps() const { return timestamps_; }
    569     const std::deque<UniqueTid>& utids() const { return utids_; }
    570     const std::deque<uint8_t>& prios() const { return prios_; }
    571     const std::deque<StringId>& tag_ids() const { return tag_ids_; }
    572     const std::deque<StringId>& msg_ids() const { return msg_ids_; }
    573 
    574    private:
    575     std::deque<int64_t> timestamps_;
    576     std::deque<UniqueTid> utids_;
    577     std::deque<uint8_t> prios_;
    578     std::deque<StringId> tag_ids_;
    579     std::deque<StringId> msg_ids_;
    580   };
    581 
    582   struct Stats {
    583     using IndexMap = std::map<int, int64_t>;
    584     int64_t value = 0;
    585     IndexMap indexed_values;
    586   };
    587   using StatsMap = std::array<Stats, stats::kNumKeys>;
    588 
    589   class HeapProfileFrames {
    590    public:
    591     struct Row {
    592       StringId name_id;
    593       int64_t mapping_row;
    594       int64_t rel_pc;
    595 
    596       bool operator==(const Row& other) const {
    597         return std::tie(name_id, mapping_row, rel_pc) ==
    598                std::tie(other.name_id, other.mapping_row, other.rel_pc);
    599       }
    600     };
    601 
    602     int64_t Insert(const Row& row) {
    603       names_.emplace_back(row.name_id);
    604       mappings_.emplace_back(row.mapping_row);
    605       rel_pcs_.emplace_back(row.rel_pc);
    606       return static_cast<int64_t>(names_.size()) - 1;
    607     }
    608 
    609     const std::deque<StringId>& names() const { return names_; }
    610     const std::deque<int64_t>& mappings() const { return mappings_; }
    611     const std::deque<int64_t>& rel_pcs() const { return rel_pcs_; }
    612 
    613    private:
    614     std::deque<StringId> names_;
    615     std::deque<int64_t> mappings_;
    616     std::deque<int64_t> rel_pcs_;
    617   };
    618 
    619   class HeapProfileCallsites {
    620    public:
    621     struct Row {
    622       int64_t depth;
    623       int64_t parent_id;
    624       int64_t frame_row;
    625 
    626       bool operator==(const Row& other) const {
    627         return std::tie(depth, parent_id, frame_row) ==
    628                std::tie(other.depth, other.parent_id, other.frame_row);
    629       }
    630     };
    631 
    632     int64_t Insert(const Row& row) {
    633       frame_depths_.emplace_back(row.depth);
    634       parent_callsite_ids_.emplace_back(row.parent_id);
    635       frame_ids_.emplace_back(row.frame_row);
    636       return static_cast<int64_t>(frame_depths_.size()) - 1;
    637     }
    638 
    639     const std::deque<int64_t>& frame_depths() const { return frame_depths_; }
    640     const std::deque<int64_t>& parent_callsite_ids() const {
    641       return parent_callsite_ids_;
    642     }
    643     const std::deque<int64_t>& frame_ids() const { return frame_ids_; }
    644 
    645    private:
    646     std::deque<int64_t> frame_depths_;
    647     std::deque<int64_t> parent_callsite_ids_;
    648     std::deque<int64_t> frame_ids_;
    649   };
    650 
    651   class HeapProfileMappings {
    652    public:
    653     struct Row {
    654       StringId build_id;
    655       int64_t offset;
    656       int64_t start;
    657       int64_t end;
    658       int64_t load_bias;
    659       StringId name_id;
    660 
    661       bool operator==(const Row& other) const {
    662         return std::tie(build_id, offset, start, end, load_bias, name_id) ==
    663                std::tie(other.build_id, other.offset, other.start, other.end,
    664                         other.load_bias, other.name_id);
    665       }
    666     };
    667 
    668     int64_t Insert(const Row& row) {
    669       build_ids_.emplace_back(row.build_id);
    670       offsets_.emplace_back(row.offset);
    671       starts_.emplace_back(row.start);
    672       ends_.emplace_back(row.end);
    673       load_biases_.emplace_back(row.load_bias);
    674       names_.emplace_back(row.name_id);
    675       return static_cast<int64_t>(build_ids_.size()) - 1;
    676     }
    677 
    678     const std::deque<StringId>& build_ids() const { return build_ids_; }
    679     const std::deque<int64_t>& offsets() const { return offsets_; }
    680     const std::deque<int64_t>& starts() const { return starts_; }
    681     const std::deque<int64_t>& ends() const { return ends_; }
    682     const std::deque<int64_t>& load_biases() const { return load_biases_; }
    683     const std::deque<StringId>& names() const { return names_; }
    684 
    685    private:
    686     std::deque<StringId> build_ids_;
    687     std::deque<int64_t> offsets_;
    688     std::deque<int64_t> starts_;
    689     std::deque<int64_t> ends_;
    690     std::deque<int64_t> load_biases_;
    691     std::deque<StringId> names_;
    692   };
    693 
    694   class HeapProfileAllocations {
    695    public:
    696     struct Row {
    697       int64_t timestamp;
    698       int64_t pid;
    699       int64_t callsite_id;
    700       int64_t count;
    701       int64_t size;
    702     };
    703 
    704     void Insert(const Row& row) {
    705       timestamps_.emplace_back(row.timestamp);
    706       pids_.emplace_back(row.pid);
    707       callsite_ids_.emplace_back(row.callsite_id);
    708       counts_.emplace_back(row.count);
    709       sizes_.emplace_back(row.size);
    710     }
    711 
    712     const std::deque<int64_t>& timestamps() const { return timestamps_; }
    713     const std::deque<int64_t>& pids() const { return pids_; }
    714     const std::deque<int64_t>& callsite_ids() const { return callsite_ids_; }
    715     const std::deque<int64_t>& counts() const { return counts_; }
    716     const std::deque<int64_t>& sizes() const { return sizes_; }
    717 
    718    private:
    719     std::deque<int64_t> timestamps_;
    720     std::deque<int64_t> pids_;
    721     std::deque<int64_t> callsite_ids_;
    722     std::deque<int64_t> counts_;
    723     std::deque<int64_t> sizes_;
    724   };
    725 
    726   void ResetStorage();
    727 
    728   UniqueTid AddEmptyThread(uint32_t tid) {
    729     unique_threads_.emplace_back(tid);
    730     return static_cast<UniqueTid>(unique_threads_.size() - 1);
    731   }
    732 
    733   UniquePid AddEmptyProcess(uint32_t pid) {
    734     unique_processes_.emplace_back(pid);
    735     return static_cast<UniquePid>(unique_processes_.size() - 1);
    736   }
    737 
    738   // Return an unqiue identifier for the contents of each string.
    739   // The string is copied internally and can be destroyed after this called.
    740   // Virtual for testing.
    741   virtual StringId InternString(base::StringView str) {
    742     return string_pool_.InternString(str);
    743   }
    744 
    745   Process* GetMutableProcess(UniquePid upid) {
    746     PERFETTO_DCHECK(upid < unique_processes_.size());
    747     return &unique_processes_[upid];
    748   }
    749 
    750   Thread* GetMutableThread(UniqueTid utid) {
    751     PERFETTO_DCHECK(utid < unique_threads_.size());
    752     return &unique_threads_[utid];
    753   }
    754 
    755   // Example usage: SetStats(stats::android_log_num_failed, 42);
    756   void SetStats(size_t key, int64_t value) {
    757     PERFETTO_DCHECK(key < stats::kNumKeys);
    758     PERFETTO_DCHECK(stats::kTypes[key] == stats::kSingle);
    759     stats_[key].value = value;
    760   }
    761 
    762   // Example usage: IncrementStats(stats::android_log_num_failed, -1);
    763   void IncrementStats(size_t key, int64_t increment = 1) {
    764     PERFETTO_DCHECK(key < stats::kNumKeys);
    765     PERFETTO_DCHECK(stats::kTypes[key] == stats::kSingle);
    766     stats_[key].value += increment;
    767   }
    768 
    769   // Example usage: IncrementIndexedStats(stats::cpu_failure, 1);
    770   void IncrementIndexedStats(size_t key, int index, int64_t increment = 1) {
    771     PERFETTO_DCHECK(key < stats::kNumKeys);
    772     PERFETTO_DCHECK(stats::kTypes[key] == stats::kIndexed);
    773     stats_[key].indexed_values[index] += increment;
    774   }
    775 
    776   // Example usage: SetIndexedStats(stats::cpu_failure, 1, 42);
    777   void SetIndexedStats(size_t key, int index, int64_t value) {
    778     PERFETTO_DCHECK(key < stats::kNumKeys);
    779     PERFETTO_DCHECK(stats::kTypes[key] == stats::kIndexed);
    780     stats_[key].indexed_values[index] = value;
    781   }
    782 
    783   class ScopedStatsTracer {
    784    public:
    785     ScopedStatsTracer(TraceStorage* storage, size_t key)
    786         : storage_(storage), key_(key), start_ns_(base::GetWallTimeNs()) {}
    787 
    788     ~ScopedStatsTracer() {
    789       if (!storage_)
    790         return;
    791       auto delta_ns = base::GetWallTimeNs() - start_ns_;
    792       storage_->IncrementStats(key_, delta_ns.count());
    793     }
    794 
    795     ScopedStatsTracer(ScopedStatsTracer&& other) noexcept { MoveImpl(&other); }
    796 
    797     ScopedStatsTracer& operator=(ScopedStatsTracer&& other) {
    798       MoveImpl(&other);
    799       return *this;
    800     }
    801 
    802    private:
    803     ScopedStatsTracer(const ScopedStatsTracer&) = delete;
    804     ScopedStatsTracer& operator=(const ScopedStatsTracer&) = delete;
    805 
    806     void MoveImpl(ScopedStatsTracer* other) {
    807       storage_ = other->storage_;
    808       key_ = other->key_;
    809       start_ns_ = other->start_ns_;
    810       other->storage_ = nullptr;
    811     }
    812 
    813     TraceStorage* storage_;
    814     size_t key_;
    815     base::TimeNanos start_ns_;
    816   };
    817 
    818   ScopedStatsTracer TraceExecutionTimeIntoStats(size_t key) {
    819     return ScopedStatsTracer(this, key);
    820   }
    821 
    822   // Reading methods.
    823   NullTermStringView GetString(StringId id) const {
    824     return string_pool_.Get(id);
    825   }
    826 
    827   const Process& GetProcess(UniquePid upid) const {
    828     PERFETTO_DCHECK(upid < unique_processes_.size());
    829     return unique_processes_[upid];
    830   }
    831 
    832   const Thread& GetThread(UniqueTid utid) const {
    833     // Allow utid == 0 for idle thread retrieval.
    834     PERFETTO_DCHECK(utid < unique_threads_.size());
    835     return unique_threads_[utid];
    836   }
    837 
    838   static RowId CreateRowId(TableId table, uint32_t row) {
    839     return (static_cast<RowId>(table) << kRowIdTableShift) | row;
    840   }
    841 
    842   static std::pair<int8_t /*table*/, uint32_t /*row*/> ParseRowId(RowId rowid) {
    843     auto id = static_cast<uint64_t>(rowid);
    844     auto table_id = static_cast<uint8_t>(id >> kRowIdTableShift);
    845     auto row = static_cast<uint32_t>(id & ((1ull << kRowIdTableShift) - 1));
    846     return std::make_pair(table_id, row);
    847   }
    848 
    849   const Slices& slices() const { return slices_; }
    850   Slices* mutable_slices() { return &slices_; }
    851 
    852   const NestableSlices& nestable_slices() const { return nestable_slices_; }
    853   NestableSlices* mutable_nestable_slices() { return &nestable_slices_; }
    854 
    855   const CounterDefinitions& counter_definitions() const {
    856     return counter_definitions_;
    857   }
    858   CounterDefinitions* mutable_counter_definitions() {
    859     return &counter_definitions_;
    860   }
    861 
    862   const CounterValues& counter_values() const { return counter_values_; }
    863   CounterValues* mutable_counter_values() { return &counter_values_; }
    864 
    865   const SqlStats& sql_stats() const { return sql_stats_; }
    866   SqlStats* mutable_sql_stats() { return &sql_stats_; }
    867 
    868   const Instants& instants() const { return instants_; }
    869   Instants* mutable_instants() { return &instants_; }
    870 
    871   const AndroidLogs& android_logs() const { return android_log_; }
    872   AndroidLogs* mutable_android_log() { return &android_log_; }
    873 
    874   const StatsMap& stats() const { return stats_; }
    875 
    876   const Args& args() const { return args_; }
    877   Args* mutable_args() { return &args_; }
    878 
    879   const RawEvents& raw_events() const { return raw_events_; }
    880   RawEvents* mutable_raw_events() { return &raw_events_; }
    881 
    882   const HeapProfileMappings& heap_profile_mappings() const {
    883     return heap_profile_mappings_;
    884   }
    885   HeapProfileMappings* mutable_heap_profile_mappings() {
    886     return &heap_profile_mappings_;
    887   }
    888 
    889   const HeapProfileFrames& heap_profile_frames() const {
    890     return heap_profile_frames_;
    891   }
    892   HeapProfileFrames* mutable_heap_profile_frames() {
    893     return &heap_profile_frames_;
    894   }
    895 
    896   const HeapProfileCallsites& heap_profile_callsites() const {
    897     return heap_profile_callsites_;
    898   }
    899   HeapProfileCallsites* mutable_heap_profile_callsites() {
    900     return &heap_profile_callsites_;
    901   }
    902 
    903   const HeapProfileAllocations& heap_profile_allocations() const {
    904     return heap_profile_allocations_;
    905   }
    906   HeapProfileAllocations* mutable_heap_profile_allocations() {
    907     return &heap_profile_allocations_;
    908   }
    909 
    910   const StringPool& string_pool() const { return string_pool_; }
    911 
    912   // |unique_processes_| always contains at least 1 element becuase the 0th ID
    913   // is reserved to indicate an invalid process.
    914   size_t process_count() const { return unique_processes_.size(); }
    915 
    916   // |unique_threads_| always contains at least 1 element becuase the 0th ID
    917   // is reserved to indicate an invalid thread.
    918   size_t thread_count() const { return unique_threads_.size(); }
    919 
    920   // Number of interned strings in the pool. Includes the empty string w/ ID=0.
    921   size_t string_count() const { return string_pool_.size(); }
    922 
    923   // Start / end ts (in nanoseconds) across the parsed trace events.
    924   // Returns (0, 0) if the trace is empty.
    925   std::pair<int64_t, int64_t> GetTraceTimestampBoundsNs() const;
    926 
    927  private:
    928   static constexpr uint8_t kRowIdTableShift = 32;
    929 
    930   using StringHash = uint64_t;
    931 
    932   TraceStorage(const TraceStorage&) = delete;
    933   TraceStorage& operator=(const TraceStorage&) = delete;
    934 
    935   TraceStorage(TraceStorage&&) = default;
    936   TraceStorage& operator=(TraceStorage&&) = default;
    937 
    938   // Stats about parsing the trace.
    939   StatsMap stats_{};
    940 
    941   // One entry for each CPU in the trace.
    942   Slices slices_;
    943 
    944   // Args for all other tables.
    945   Args args_;
    946 
    947   // One entry for each unique string in the trace.
    948   StringPool string_pool_;
    949 
    950   // One entry for each UniquePid, with UniquePid as the index.
    951   // Never hold on to pointers to Process, as vector resize will
    952   // invalidate them.
    953   std::vector<Process> unique_processes_;
    954 
    955   // One entry for each UniqueTid, with UniqueTid as the index.
    956   std::deque<Thread> unique_threads_;
    957 
    958   // Slices coming from userspace events (e.g. Chromium TRACE_EVENT macros).
    959   NestableSlices nestable_slices_;
    960 
    961   // The type of counters in the trace. Can be thought of the the "metadata".
    962   CounterDefinitions counter_definitions_;
    963 
    964   // The values from the Counter events from the trace. This includes CPU
    965   // frequency events as well systrace trace_marker counter events.
    966   CounterValues counter_values_;
    967 
    968   SqlStats sql_stats_;
    969 
    970   // These are instantaneous events in the trace. They have no duration
    971   // and do not have a value that make sense to track over time.
    972   // e.g. signal events
    973   Instants instants_;
    974 
    975   // Raw events are every ftrace event in the trace. The raw event includes
    976   // the timestamp and the pid. The args for the raw event will be in the
    977   // args table. This table can be used to generate a text version of the
    978   // trace.
    979   RawEvents raw_events_;
    980   AndroidLogs android_log_;
    981 
    982   HeapProfileMappings heap_profile_mappings_;
    983   HeapProfileFrames heap_profile_frames_;
    984   HeapProfileCallsites heap_profile_callsites_;
    985   HeapProfileAllocations heap_profile_allocations_;
    986 };
    987 
    988 }  // namespace trace_processor
    989 }  // namespace perfetto
    990 
    991 namespace std {
    992 
    993 template <>
    994 struct hash<::perfetto::trace_processor::TraceStorage::HeapProfileFrames::Row> {
    995   using argument_type =
    996       ::perfetto::trace_processor::TraceStorage::HeapProfileFrames::Row;
    997   using result_type = size_t;
    998 
    999   result_type operator()(const argument_type& r) const {
   1000     return std::hash<::perfetto::trace_processor::StringId>{}(r.name_id) ^
   1001            std::hash<int64_t>{}(r.mapping_row) ^ std::hash<int64_t>{}(r.rel_pc);
   1002   }
   1003 };
   1004 
   1005 template <>
   1006 struct hash<
   1007     ::perfetto::trace_processor::TraceStorage::HeapProfileCallsites::Row> {
   1008   using argument_type =
   1009       ::perfetto::trace_processor::TraceStorage::HeapProfileCallsites::Row;
   1010   using result_type = size_t;
   1011 
   1012   result_type operator()(const argument_type& r) const {
   1013     return std::hash<int64_t>{}(r.depth) ^ std::hash<int64_t>{}(r.parent_id) ^
   1014            std::hash<int64_t>{}(r.frame_row);
   1015   }
   1016 };
   1017 
   1018 template <>
   1019 struct hash<
   1020     ::perfetto::trace_processor::TraceStorage::HeapProfileMappings::Row> {
   1021   using argument_type =
   1022       ::perfetto::trace_processor::TraceStorage::HeapProfileMappings::Row;
   1023   using result_type = size_t;
   1024 
   1025   result_type operator()(const argument_type& r) const {
   1026     return std::hash<::perfetto::trace_processor::StringId>{}(r.build_id) ^
   1027            std::hash<int64_t>{}(r.offset) ^ std::hash<int64_t>{}(r.start) ^
   1028            std::hash<int64_t>{}(r.end) ^ std::hash<int64_t>{}(r.load_bias) ^
   1029            std::hash<::perfetto::trace_processor::StringId>{}(r.name_id);
   1030   }
   1031 };
   1032 
   1033 }  // namespace std
   1034 
   1035 #endif  // SRC_TRACE_PROCESSOR_TRACE_STORAGE_H_
   1036