• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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