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 "sched_slice_table.h"
17
18 #include <cmath>
19
20 namespace SysTuning {
21 namespace TraceStreamer {
22 enum class Index : int32_t { ID = 0, TS, DUR, TS_END, CPU, INTERNAL_TID, INTERNAL_PID, END_STATE, PRIORITY, ARGSETID };
SchedSliceTable(const TraceDataCache * dataCache)23 SchedSliceTable::SchedSliceTable(const TraceDataCache *dataCache) : TableBase(dataCache)
24 {
25 tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
26 tableColumn_.push_back(TableBase::ColumnInfo("ts", "INTEGER"));
27 tableColumn_.push_back(TableBase::ColumnInfo("dur", "INTEGER"));
28 tableColumn_.push_back(TableBase::ColumnInfo("ts_end", "INTEGER"));
29 tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER"));
30 tableColumn_.push_back(TableBase::ColumnInfo("itid", "INTEGER"));
31 tableColumn_.push_back(TableBase::ColumnInfo("ipid", "INTEGER"));
32 tableColumn_.push_back(TableBase::ColumnInfo("end_state", "TEXT"));
33 tableColumn_.push_back(TableBase::ColumnInfo("priority", "INTEGER"));
34 tableColumn_.push_back(TableBase::ColumnInfo("arg_setid", "INTEGER"));
35 tablePriKey_.push_back("id");
36 }
37
~SchedSliceTable()38 SchedSliceTable::~SchedSliceTable() {}
39
FilterByConstraint(FilterConstraints & schedfc,double & schedfilterCost,size_t schedrowCount,uint32_t schedcurrenti)40 void SchedSliceTable::FilterByConstraint(FilterConstraints &schedfc,
41 double &schedfilterCost,
42 size_t schedrowCount,
43 uint32_t schedcurrenti)
44 {
45 // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
46 // for loop
47 const auto &schedc = schedfc.GetConstraints()[schedcurrenti];
48 switch (static_cast<Index>(schedc.col)) {
49 case Index::ID: {
50 if (CanFilterId(schedc.op, schedrowCount)) {
51 schedfc.UpdateConstraint(schedcurrenti, true);
52 schedfilterCost += 1; // id can position by 1 step
53 } else {
54 schedfilterCost += schedrowCount; // scan all rows
55 }
56 break;
57 }
58 case Index::TS: {
59 auto schedoldRowCount = schedrowCount;
60 if (CanFilterSorted(schedc.op, schedrowCount)) {
61 schedfc.UpdateConstraint(schedcurrenti, true);
62 schedfilterCost += log2(schedoldRowCount); // binary search
63 } else {
64 schedfilterCost += schedoldRowCount;
65 }
66 break;
67 }
68 default: // other column
69 schedfilterCost += schedrowCount; // scan all rows
70 break;
71 }
72 }
73
CreateCursor()74 std::unique_ptr<TableBase::Cursor> SchedSliceTable::CreateCursor()
75 {
76 return std::make_unique<Cursor>(dataCache_, this);
77 }
78
Cursor(const TraceDataCache * dataCache,TableBase * table)79 SchedSliceTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
80 : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstSchedSliceData().Size())),
81 schedSliceObj_(dataCache->GetConstSchedSliceData())
82 {
83 }
84
~Cursor()85 SchedSliceTable::Cursor::~Cursor() {}
86
Filter(const FilterConstraints & fc,sqlite3_value ** argv)87 int32_t SchedSliceTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
88 {
89 // reset indexMap_
90 indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
91
92 if (rowCount_ <= 0) {
93 return SQLITE_OK;
94 }
95
96 auto schedSliceTabCs = fc.GetConstraints();
97 std::set<uint32_t> sId = {static_cast<uint32_t>(Index::TS)};
98 SwapIndexFront(schedSliceTabCs, sId);
99 for (size_t i = 0; i < schedSliceTabCs.size(); i++) {
100 const auto &c = schedSliceTabCs[i];
101 switch (static_cast<Index>(c.col)) {
102 case Index::ID:
103 FilterId(c.op, argv[c.idxInaConstraint]);
104 break;
105 case Index::TS:
106 FilterTS(c.op, argv[c.idxInaConstraint], schedSliceObj_.TimeStampData());
107 break;
108 case Index::CPU:
109 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[c.idxInaConstraint])),
110 schedSliceObj_.CpusData());
111 break;
112 case Index::INTERNAL_TID:
113 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[c.idxInaConstraint])),
114 schedSliceObj_.InternalTidsData());
115 break;
116 case Index::INTERNAL_PID:
117 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[c.idxInaConstraint])),
118 schedSliceObj_.InternalPidsData());
119 break;
120 case Index::DUR:
121 indexMap_->MixRange(c.op, static_cast<uint64_t>(sqlite3_value_int64(argv[c.idxInaConstraint])),
122 schedSliceObj_.DursData());
123 break;
124 default:
125 break;
126 }
127 }
128
129 auto schedSliceOrderbys = fc.GetOrderBys();
130 for (auto i = schedSliceOrderbys.size(); i > 0;) {
131 i--;
132 switch (static_cast<Index>(schedSliceOrderbys[i].iColumn)) {
133 case Index::ID:
134 case Index::TS:
135 indexMap_->SortBy(schedSliceOrderbys[i].desc);
136 break;
137 default:
138 break;
139 }
140 }
141
142 return SQLITE_OK;
143 }
144
Column(int32_t col) const145 int32_t SchedSliceTable::Cursor::Column(int32_t col) const
146 {
147 switch (static_cast<Index>(col)) {
148 case Index::ID:
149 sqlite3_result_int64(context_, static_cast<int32_t>(schedSliceObj_.IdsData()[CurrentRow()]));
150 break;
151 case Index::TS:
152 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.TimeStampData()[CurrentRow()]));
153 break;
154 case Index::DUR:
155 SetTypeColumnInt64(schedSliceObj_.DursData()[CurrentRow()], INVALID_UINT64);
156 break;
157 case Index::TS_END:
158 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.TsEndData()[CurrentRow()]));
159 break;
160 case Index::CPU:
161 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.CpusData()[CurrentRow()]));
162 break;
163 case Index::INTERNAL_TID:
164 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.InternalTidsData()[CurrentRow()]));
165 break;
166 case Index::INTERNAL_PID:
167 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.InternalPidsData()[CurrentRow()]));
168 break;
169 case Index::END_STATE: {
170 const std::string &str = dataCache_->GetConstSchedStateData(schedSliceObj_.EndStatesData()[CurrentRow()]);
171 sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr);
172 break;
173 }
174 case Index::PRIORITY:
175 sqlite3_result_int(context_, schedSliceObj_.PriorityData()[CurrentRow()]);
176 break;
177 case Index::ARGSETID: {
178 const uint32_t &argSetId = schedSliceObj_.ArgSetData()[CurrentRow()];
179 if (argSetId != INVALID_UINT32) {
180 sqlite3_result_int(context_, argSetId);
181 }
182 break;
183 }
184 default:
185 TS_LOGF("Unregistered column : %d", col);
186 break;
187 }
188 return SQLITE_OK;
189 }
190
GetOrbyes(FilterConstraints & schedfc,EstimatedIndexInfo & schedei)191 void SchedSliceTable::GetOrbyes(FilterConstraints &schedfc, EstimatedIndexInfo &schedei)
192 {
193 auto schedorderbys = schedfc.GetOrderBys();
194 for (auto i = 0; i < schedorderbys.size(); i++) {
195 switch (static_cast<Index>(schedorderbys[i].iColumn)) {
196 case Index::ID:
197 case Index::TS:
198 break;
199 default: // other columns can be sorted by SQLite
200 schedei.isOrdered = false;
201 break;
202 }
203 }
204 }
205 } // namespace TraceStreamer
206 } // namespace SysTuning
207