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