1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "perf_call_chain_table.h"
17
18 namespace SysTuning {
19 namespace TraceStreamer {
20 enum class Index : int32_t {
21 ID = 0,
22 CALLCHAIN_ID,
23 DEPTH,
24 IP,
25 VADDR_IN_FILE,
26 OFFSET_TO_VADDR,
27 FILE_ID,
28 SYMBOL_ID,
29 NAME,
30 SOURCE_FILE_ID,
31 LINE_NUMBER
32 };
PerfCallChainTable(const TraceDataCache * dataCache)33 PerfCallChainTable::PerfCallChainTable(const TraceDataCache *dataCache) : TableBase(dataCache)
34 {
35 tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
36 tableColumn_.push_back(TableBase::ColumnInfo("callchain_id", "INTEGER"));
37 tableColumn_.push_back(TableBase::ColumnInfo("depth", "INTEGER"));
38 tableColumn_.push_back(TableBase::ColumnInfo("ip", "INTEGER"));
39 tableColumn_.push_back(TableBase::ColumnInfo("vaddr_in_file", "INTEGER"));
40 tableColumn_.push_back(TableBase::ColumnInfo("offset_to_vaddr", "INTEGER"));
41 tableColumn_.push_back(TableBase::ColumnInfo("file_id", "INTEGER"));
42 tableColumn_.push_back(TableBase::ColumnInfo("symbol_id", "INTEGER"));
43 tableColumn_.push_back(TableBase::ColumnInfo("name", "INTEGER"));
44 tableColumn_.push_back(TableBase::ColumnInfo("source_file_id", "INTEGER"));
45 tableColumn_.push_back(TableBase::ColumnInfo("line_number", "INTEGER"));
46 tablePriKey_.push_back("id");
47 }
48
~PerfCallChainTable()49 PerfCallChainTable::~PerfCallChainTable() {}
50
FilterByConstraint(FilterConstraints & chainfc,double & chainfilterCost,size_t chainrowCount,uint32_t chaincurrenti)51 void PerfCallChainTable::FilterByConstraint(FilterConstraints &chainfc,
52 double &chainfilterCost,
53 size_t chainrowCount,
54 uint32_t chaincurrenti)
55 {
56 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
57 // for loop
58 const auto &chainc = chainfc.GetConstraints()[chaincurrenti];
59 switch (static_cast<Index>(chainc.col)) {
60 case Index::ID: {
61 if (CanFilterId(chainc.op, chainrowCount)) {
62 chainfc.UpdateConstraint(chaincurrenti, true);
63 chainfilterCost += 1; // id can position by 1 step
64 } else {
65 chainfilterCost += chainrowCount; // scan all rows
66 }
67 break;
68 }
69 default: // other column
70 chainfilterCost += chainrowCount; // scan all rows
71 break;
72 }
73 }
74
CreateCursor()75 std::unique_ptr<TableBase::Cursor> PerfCallChainTable::CreateCursor()
76 {
77 return std::make_unique<Cursor>(dataCache_, this);
78 }
79
Cursor(const TraceDataCache * dataCache,TableBase * table)80 PerfCallChainTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
81 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstPerfCallChainData().Size())),
82 perfCallChainObj_(dataCache->GetConstPerfCallChainData())
83 {
84 }
85
~Cursor()86 PerfCallChainTable::Cursor::~Cursor() {}
87
Filter(const FilterConstraints & fc,sqlite3_value ** argv)88 int32_t PerfCallChainTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
89 {
90 // reset indexMap_
91 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
92
93 if (rowCount_ <= 0) {
94 return SQLITE_OK;
95 }
96
97 auto perfCallChainCs = fc.GetConstraints();
98 std::set<uint32_t> sId = {static_cast<uint32_t>(Index::ID)};
99 SwapIndexFront(perfCallChainCs, sId);
100 for (size_t i = 0; i < perfCallChainCs.size(); i++) {
101 const auto &c = perfCallChainCs[i];
102 switch (static_cast<Index>(c.col)) {
103 case Index::ID:
104 FilterId(c.op, argv[c.idxInaConstraint]);
105 break;
106 case Index::CALLCHAIN_ID:
107 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
108 perfCallChainObj_.CallChainIds());
109 break;
110 case Index::FILE_ID:
111 indexMap_->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
112 perfCallChainObj_.FileIds());
113 break;
114 case Index::SYMBOL_ID:
115 indexMap_->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
116 perfCallChainObj_.SymbolIds());
117 break;
118 default:
119 break;
120 }
121 }
122
123 auto perfCallChainOrderbys = fc.GetOrderBys();
124 for (auto i = perfCallChainOrderbys.size(); i > 0;) {
125 i--;
126 switch (static_cast<Index>(perfCallChainOrderbys[i].iColumn)) {
127 case Index::ID:
128 indexMap_->SortBy(perfCallChainOrderbys[i].desc);
129 break;
130 default:
131 break;
132 }
133 }
134
135 return SQLITE_OK;
136 }
137
Column(int32_t column) const138 int32_t PerfCallChainTable::Cursor::Column(int32_t column) const
139 {
140 switch (static_cast<Index>(column)) {
141 case Index::ID:
142 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.IdsData()[CurrentRow()]));
143 break;
144 case Index::CALLCHAIN_ID:
145 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.CallChainIds()[CurrentRow()]));
146 break;
147 case Index::DEPTH:
148 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.Depths()[CurrentRow()]));
149 break;
150 case Index::IP:
151 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.Ips()[CurrentRow()]));
152 break;
153 case Index::VADDR_IN_FILE:
154 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.VaddrInFiles()[CurrentRow()]));
155 break;
156 case Index::OFFSET_TO_VADDR:
157 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.OffsetToVaddrs()[CurrentRow()]));
158 break;
159 case Index::FILE_ID:
160 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.FileIds()[CurrentRow()]));
161 break;
162 case Index::SYMBOL_ID:
163 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.SymbolIds()[CurrentRow()]));
164 break;
165 case Index::NAME:
166 sqlite3_result_int64(context_, static_cast<uint64_t>(perfCallChainObj_.Names()[CurrentRow()]));
167 break;
168 case Index::SOURCE_FILE_ID:
169 SetTypeColumnInt64(perfCallChainObj_.SourceFileIds()[CurrentRow()], INVALID_UINT64);
170 break;
171 case Index::LINE_NUMBER:
172 SetTypeColumnInt64(perfCallChainObj_.LineNumbers()[CurrentRow()], INVALID_UINT64);
173 break;
174 default:
175 TS_LOGF("Unregistered column : %d", column);
176 break;
177 }
178 return SQLITE_OK;
179 }
180
GetOrbyes(FilterConstraints & chainfc,EstimatedIndexInfo & chainei)181 void PerfCallChainTable::GetOrbyes(FilterConstraints &chainfc, EstimatedIndexInfo &chainei)
182 {
183 auto chainorderbys = chainfc.GetOrderBys();
184 for (auto i = 0; i < chainorderbys.size(); i++) {
185 switch (static_cast<Index>(chainorderbys[i].iColumn)) {
186 case Index::ID:
187 break;
188 default: // other columns can be sorted by SQLite
189 chainei.isOrdered = false;
190 break;
191 }
192 }
193 }
194 } // namespace TraceStreamer
195 } // namespace SysTuning
196