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 base::Status ExperimentalCounterDurGenerator::ValidateConstraints(
47 const QueryConstraints&) {
48 return base::OkStatus();
49 }
50
ComputeTable(const std::vector<Constraint> &,const std::vector<Order> &,const BitVector &,std::unique_ptr<Table> & table_return)51 base::Status ExperimentalCounterDurGenerator::ComputeTable(
52 const std::vector<Constraint>&,
53 const std::vector<Order>&,
54 const BitVector&,
55 std::unique_ptr<Table>& table_return) {
56 if (!dur_column_) {
57 dur_column_.reset(
58 new NullableVector<int64_t>(ComputeDurColumn(*counter_table_)));
59 delta_column_.reset(
60 new NullableVector<double>(ComputeDeltaColumn(*counter_table_)));
61 }
62
63 Table t = counter_table_
64 ->ExtendWithColumn("dur", std::move(dur_column_.get()),
65 TypedColumn<int64_t>::default_flags())
66 .ExtendWithColumn("delta", std::move(delta_column_.get()),
67 TypedColumn<int64_t>::default_flags());
68
69 table_return.reset(new Table(t.Copy()));
70 return base::OkStatus();
71 }
72
73 // static
ComputeDurColumn(const Table & table)74 NullableVector<int64_t> ExperimentalCounterDurGenerator::ComputeDurColumn(
75 const Table& table) {
76 // Keep track of the last seen row for each track id.
77 std::unordered_map<TrackId, uint32_t> last_row_for_track_id;
78 NullableVector<int64_t> dur;
79
80 const auto* ts_col =
81 TypedColumn<int64_t>::FromColumn(table.GetColumnByName("ts"));
82 const auto* track_id_col =
83 TypedColumn<tables::CounterTrackTable::Id>::FromColumn(
84 table.GetColumnByName("track_id"));
85
86 for (uint32_t i = 0; i < table.row_count(); ++i) {
87 // Check if we already have a previous row for the current track id.
88 TrackId track_id = (*track_id_col)[i];
89 auto it = last_row_for_track_id.find(track_id);
90 if (it == last_row_for_track_id.end()) {
91 // This means we don't have any row - start tracking this row for the
92 // future.
93 last_row_for_track_id.emplace(track_id, i);
94 } else {
95 // This means we have an previous row for the current track id. Update
96 // the duration of the previous row to be up to the current ts.
97 uint32_t old_row = it->second;
98 it->second = i;
99 dur.Set(old_row, (*ts_col)[i] - (*ts_col)[old_row]);
100 }
101 // Append -1 to mark this event as not having been finished. On a later
102 // row, we may set this to have the correct value.
103 dur.Append(-1);
104 }
105 return dur;
106 }
107
108 // static
ComputeDeltaColumn(const Table & table)109 NullableVector<double> ExperimentalCounterDurGenerator::ComputeDeltaColumn(
110 const Table& table) {
111 // Keep track of the last seen row for each track id.
112 std::unordered_map<TrackId, uint32_t> last_row_for_track_id;
113 NullableVector<double> delta;
114
115 const auto* value_col =
116 TypedColumn<double>::FromColumn(table.GetColumnByName("value"));
117 const auto* track_id_col =
118 TypedColumn<tables::CounterTrackTable::Id>::FromColumn(
119 table.GetColumnByName("track_id"));
120
121 for (uint32_t i = 0; i < table.row_count(); ++i) {
122 // Check if we already have a previous row for the current track id.
123 TrackId track_id = (*track_id_col)[i];
124 auto it = last_row_for_track_id.find(track_id);
125 if (it == last_row_for_track_id.end()) {
126 // This means we don't have any row - start tracking this row for the
127 // future.
128 last_row_for_track_id.emplace(track_id, i);
129 } else {
130 // This means we have an previous row for the current track id. Update
131 // the duration of the previous row to be up to the current ts.
132 uint32_t old_row = it->second;
133 it->second = i;
134 delta.Set(old_row, (*value_col)[i] - (*value_col)[old_row]);
135 }
136 delta.Append(0);
137 }
138 return delta;
139 }
140
141 } // namespace trace_processor
142 } // namespace perfetto
143