• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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/dynamic/experimental_counter_dur_generator.h"
18 
19 namespace perfetto {
20 namespace trace_processor {
21 
ExperimentalCounterDurGenerator(const tables::CounterTable & table)22 ExperimentalCounterDurGenerator::ExperimentalCounterDurGenerator(
23     const tables::CounterTable& table)
24     : counter_table_(&table) {}
25 ExperimentalCounterDurGenerator::~ExperimentalCounterDurGenerator() = default;
26 
CreateSchema()27 Table::Schema ExperimentalCounterDurGenerator::CreateSchema() {
28   Table::Schema schema = tables::CounterTable::Schema();
29   schema.columns.emplace_back(
30       Table::Schema::Column{"dur", SqlValue::Type::kLong, false /* is_id */,
31                             false /* is_sorted */, false /* is_hidden */});
32   schema.columns.emplace_back(
33       Table::Schema::Column{"delta", SqlValue::Type::kLong, false /* is_id */,
34                             false /* is_sorted */, false /* is_hidden */});
35   return schema;
36 }
37 
TableName()38 std::string ExperimentalCounterDurGenerator::TableName() {
39   return "experimental_counter_dur";
40 }
41 
EstimateRowCount()42 uint32_t ExperimentalCounterDurGenerator::EstimateRowCount() {
43   return counter_table_->row_count();
44 }
45 
ValidateConstraints(const QueryConstraints &)46 util::Status ExperimentalCounterDurGenerator::ValidateConstraints(
47     const QueryConstraints&) {
48   return util::OkStatus();
49 }
50 
ComputeTable(const std::vector<Constraint> &,const std::vector<Order> &)51 std::unique_ptr<Table> ExperimentalCounterDurGenerator::ComputeTable(
52     const std::vector<Constraint>&,
53     const std::vector<Order>&) {
54   if (!dur_column_) {
55     dur_column_.reset(
56         new NullableVector<int64_t>(ComputeDurColumn(*counter_table_)));
57     delta_column_.reset(
58         new NullableVector<double>(ComputeDeltaColumn(*counter_table_)));
59   }
60 
61   Table t = counter_table_
62                 ->ExtendWithColumn("dur", std::move(dur_column_.get()),
63                                    TypedColumn<int64_t>::default_flags())
64                 .ExtendWithColumn("delta", std::move(delta_column_.get()),
65                                   TypedColumn<int64_t>::default_flags());
66 
67   return std::unique_ptr<Table>(new Table(t.Copy()));
68 }
69 
70 // static
ComputeDurColumn(const Table & table)71 NullableVector<int64_t> ExperimentalCounterDurGenerator::ComputeDurColumn(
72     const Table& table) {
73   // Keep track of the last seen row for each track id.
74   std::unordered_map<TrackId, uint32_t> last_row_for_track_id;
75   NullableVector<int64_t> dur;
76 
77   const auto* ts_col =
78       TypedColumn<int64_t>::FromColumn(table.GetColumnByName("ts"));
79   const auto* track_id_col =
80       TypedColumn<tables::CounterTrackTable::Id>::FromColumn(
81           table.GetColumnByName("track_id"));
82 
83   for (uint32_t i = 0; i < table.row_count(); ++i) {
84     // Check if we already have a previous row for the current track id.
85     TrackId track_id = (*track_id_col)[i];
86     auto it = last_row_for_track_id.find(track_id);
87     if (it == last_row_for_track_id.end()) {
88       // This means we don't have any row - start tracking this row for the
89       // future.
90       last_row_for_track_id.emplace(track_id, i);
91     } else {
92       // This means we have an previous row for the current track id. Update
93       // the duration of the previous row to be up to the current ts.
94       uint32_t old_row = it->second;
95       it->second = i;
96       dur.Set(old_row, (*ts_col)[i] - (*ts_col)[old_row]);
97     }
98     // Append -1 to mark this event as not having been finished. On a later
99     // row, we may set this to have the correct value.
100     dur.Append(-1);
101   }
102   return dur;
103 }
104 
105 // static
ComputeDeltaColumn(const Table & table)106 NullableVector<double> ExperimentalCounterDurGenerator::ComputeDeltaColumn(
107     const Table& table) {
108   // Keep track of the last seen row for each track id.
109   std::unordered_map<TrackId, uint32_t> last_row_for_track_id;
110   NullableVector<double> delta;
111 
112   const auto* value_col =
113       TypedColumn<double>::FromColumn(table.GetColumnByName("value"));
114   const auto* track_id_col =
115       TypedColumn<tables::CounterTrackTable::Id>::FromColumn(
116           table.GetColumnByName("track_id"));
117 
118   for (uint32_t i = 0; i < table.row_count(); ++i) {
119     // Check if we already have a previous row for the current track id.
120     TrackId track_id = (*track_id_col)[i];
121     auto it = last_row_for_track_id.find(track_id);
122     if (it == last_row_for_track_id.end()) {
123       // This means we don't have any row - start tracking this row for the
124       // future.
125       last_row_for_track_id.emplace(track_id, i);
126     } else {
127       // This means we have an previous row for the current track id. Update
128       // the duration of the previous row to be up to the current ts.
129       uint32_t old_row = it->second;
130       it->second = i;
131       delta.Set(old_row, (*value_col)[i] - (*value_col)[old_row]);
132     }
133     delta.Append(0);
134   }
135   return delta;
136 }
137 
138 }  // namespace trace_processor
139 }  // namespace perfetto
140