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 = static_cast<int32_t>(schedSliceOrderbys.size()) - 1; i >= 0; i--) {
131 switch (static_cast<Index>(schedSliceOrderbys[i].iColumn)) {
132 case Index::ID:
133 case Index::TS:
134 indexMap_->SortBy(schedSliceOrderbys[i].desc);
135 break;
136 default:
137 break;
138 }
139 }
140
141 return SQLITE_OK;
142 }
143
Column(int32_t col) const144 int32_t SchedSliceTable::Cursor::Column(int32_t col) const
145 {
146 switch (static_cast<Index>(col)) {
147 case Index::ID:
148 sqlite3_result_int64(context_, static_cast<int32_t>(schedSliceObj_.IdsData()[CurrentRow()]));
149 break;
150 case Index::TS:
151 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.TimeStampData()[CurrentRow()]));
152 break;
153 case Index::DUR:
154 SetTypeColumnInt64(schedSliceObj_.DursData()[CurrentRow()], INVALID_UINT64);
155 break;
156 case Index::TS_END:
157 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.TsEndData()[CurrentRow()]));
158 break;
159 case Index::CPU:
160 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.CpusData()[CurrentRow()]));
161 break;
162 case Index::INTERNAL_TID:
163 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.InternalTidsData()[CurrentRow()]));
164 break;
165 case Index::INTERNAL_PID:
166 sqlite3_result_int64(context_, static_cast<sqlite3_int64>(schedSliceObj_.InternalPidsData()[CurrentRow()]));
167 break;
168 case Index::END_STATE: {
169 const std::string &str = dataCache_->GetConstSchedStateData(schedSliceObj_.EndStatesData()[CurrentRow()]);
170 sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr);
171 break;
172 }
173 case Index::PRIORITY:
174 sqlite3_result_int(context_, schedSliceObj_.PriorityData()[CurrentRow()]);
175 break;
176 case Index::ARGSETID: {
177 const uint32_t &argSetId = schedSliceObj_.ArgSetData()[CurrentRow()];
178 if (argSetId != INVALID_UINT32) {
179 sqlite3_result_int(context_, argSetId);
180 }
181 break;
182 }
183 default:
184 TS_LOGF("Unregistered column : %d", col);
185 break;
186 }
187 return SQLITE_OK;
188 }
189
GetOrbyes(FilterConstraints &schedfc, EstimatedIndexInfo &schedei)190 void SchedSliceTable::GetOrbyes(FilterConstraints &schedfc, EstimatedIndexInfo &schedei)
191 {
192 auto schedorderbys = schedfc.GetOrderBys();
193 for (auto i = 0; i < schedorderbys.size(); i++) {
194 switch (static_cast<Index>(schedorderbys[i].iColumn)) {
195 case Index::ID:
196 case Index::TS:
197 break;
198 default: // other columns can be sorted by SQLite
199 schedei.isOrdered = false;
200 break;
201 }
202 }
203 }
204 } // namespace TraceStreamer
205 } // namespace SysTuning
206