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