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 return schema;
33 }
34
TableName()35 std::string ExperimentalCounterDurGenerator::TableName() {
36 return "experimental_counter_dur";
37 }
38
EstimateRowCount()39 uint32_t ExperimentalCounterDurGenerator::EstimateRowCount() {
40 return counter_table_->row_count();
41 }
42
ValidateConstraints(const QueryConstraints &)43 util::Status ExperimentalCounterDurGenerator::ValidateConstraints(
44 const QueryConstraints&) {
45 return util::OkStatus();
46 }
47
ComputeTable(const std::vector<Constraint> &,const std::vector<Order> &)48 std::unique_ptr<Table> ExperimentalCounterDurGenerator::ComputeTable(
49 const std::vector<Constraint>&,
50 const std::vector<Order>&) {
51 if (!dur_column_) {
52 dur_column_.reset(
53 new NullableVector<int64_t>(ComputeDurColumn(*counter_table_)));
54 }
55 return std::unique_ptr<Table>(new Table(counter_table_->ExtendWithColumn(
56 "dur", dur_column_.get(), TypedColumn<int64_t>::default_flags())));
57 }
58
59 // static
ComputeDurColumn(const Table & table)60 NullableVector<int64_t> ExperimentalCounterDurGenerator::ComputeDurColumn(
61 const Table& table) {
62 // Keep track of the last seen row for each track id.
63 std::unordered_map<TrackId, uint32_t> last_row_for_track_id;
64 NullableVector<int64_t> dur;
65
66 const auto* ts_col =
67 TypedColumn<int64_t>::FromColumn(table.GetColumnByName("ts"));
68 const auto* track_id_col =
69 TypedColumn<tables::CounterTrackTable::Id>::FromColumn(
70 table.GetColumnByName("track_id"));
71
72 for (uint32_t i = 0; i < table.row_count(); ++i) {
73 // Check if we already have a previous row for the current track id.
74 TrackId track_id = (*track_id_col)[i];
75 auto it = last_row_for_track_id.find(track_id);
76 if (it == last_row_for_track_id.end()) {
77 // This means we don't have any row - start tracking this row for the
78 // future.
79 last_row_for_track_id.emplace(track_id, i);
80 } else {
81 // This means we have an previous row for the current track id. Update
82 // the duration of the previous row to be up to the current ts.
83 uint32_t old_row = it->second;
84 it->second = i;
85 dur.Set(old_row, (*ts_col)[i] - (*ts_col)[old_row]);
86 }
87 // Append -1 to mark this event as not having been finished. On a later
88 // row, we may set this to have the correct value.
89 dur.Append(-1);
90 }
91 return dur;
92 }
93
94 } // namespace trace_processor
95 } // namespace perfetto
96