• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "cpu_measure_filter_table.h"
17 
18 #include <cmath>
19 
20 #include "log.h"
21 
22 namespace SysTuning {
23 namespace TraceStreamer {
24 namespace {
25 enum Index { ID = 0, TYPE, NAME, CPU };
26 }
CpuMeasureFilterTable(const TraceDataCache * dataCache)27 CpuMeasureFilterTable::CpuMeasureFilterTable(const TraceDataCache* dataCache) : TableBase(dataCache)
28 {
29     tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
30     tableColumn_.push_back(TableBase::ColumnInfo("type", "TEXT"));
31     tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT"));
32     tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER"));
33     tablePriKey_.push_back("id");
34 }
35 
~CpuMeasureFilterTable()36 CpuMeasureFilterTable::~CpuMeasureFilterTable() {}
37 
EstimateFilterCost(FilterConstraints & fc,EstimatedIndexInfo & ei)38 void CpuMeasureFilterTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei)
39 {
40     constexpr double filterBaseCost = 1000.0; // set-up and tear-down
41     constexpr double indexCost = 2.0;
42     ei.estimatedCost = filterBaseCost;
43 
44     auto rowCount = dataCache_->GetConstCpuMeasureData().Size();
45     if (rowCount == 0 || rowCount == 1) {
46         ei.estimatedRows = rowCount;
47         ei.estimatedCost += indexCost * rowCount;
48         return;
49     }
50 
51     double filterCost = 0.0;
52     auto constraints = fc.GetConstraints();
53     if (constraints.empty()) { // scan all rows
54         filterCost = rowCount;
55     } else {
56         FilterByConstraint(fc, filterCost, rowCount);
57     }
58     ei.estimatedCost += filterCost;
59     ei.estimatedRows = rowCount;
60     ei.estimatedCost += rowCount * indexCost;
61 
62     ei.isOrdered = true;
63     auto orderbys = fc.GetOrderBys();
64     for (auto i = 0; i < orderbys.size(); i++) {
65         switch (orderbys[i].iColumn) {
66             case ID:
67                 break;
68             default: // other columns can be sorted by SQLite
69                 ei.isOrdered = false;
70                 break;
71         }
72     }
73 }
74 
FilterByConstraint(FilterConstraints & fc,double & filterCost,size_t rowCount)75 void CpuMeasureFilterTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount)
76 {
77     auto fcConstraints = fc.GetConstraints();
78     for (int i = 0; i < static_cast<int>(fcConstraints.size()); i++) {
79         if (rowCount <= 1) {
80             // only one row or nothing, needn't filter by constraint
81             filterCost += rowCount;
82             break;
83         }
84         const auto& c = fcConstraints[i];
85         switch (c.col) {
86             case ID: {
87                 auto oldRowCount = rowCount;
88                 if (CanFilterSorted(c.op, rowCount)) {
89                     fc.UpdateConstraint(i, true);
90                     filterCost += log2(oldRowCount); // binary search
91                 } else {
92                     filterCost += oldRowCount;
93                 }
94                 break;
95             }
96             default:                    // other column
97                 filterCost += rowCount; // scan all rows
98                 break;
99         }
100     }
101 }
102 
CanFilterSorted(const char op,size_t & rowCount) const103 bool CpuMeasureFilterTable::CanFilterSorted(const char op, size_t& rowCount) const
104 {
105     switch (op) {
106         case SQLITE_INDEX_CONSTRAINT_EQ:
107             rowCount = rowCount / log2(rowCount);
108             break;
109         case SQLITE_INDEX_CONSTRAINT_GT:
110         case SQLITE_INDEX_CONSTRAINT_GE:
111         case SQLITE_INDEX_CONSTRAINT_LE:
112         case SQLITE_INDEX_CONSTRAINT_LT:
113             rowCount = (rowCount >> 1);
114             break;
115         default:
116             return false;
117     }
118     return true;
119 }
120 
CreateCursor()121 std::unique_ptr<TableBase::Cursor> CpuMeasureFilterTable::CreateCursor()
122 {
123     return std::make_unique<Cursor>(dataCache_, this);
124 }
125 
Cursor(const TraceDataCache * dataCache,TableBase * table)126 CpuMeasureFilterTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
127     : TableBase::Cursor(dataCache, table,
128         static_cast<uint32_t>(dataCache->GetConstCpuMeasureData().Size())),
129       cpuMeasureObj_(dataCache->GetConstCpuMeasureData())
130 {
131 }
132 
~Cursor()133 CpuMeasureFilterTable::Cursor::~Cursor() {}
134 
Filter(const FilterConstraints & fc,sqlite3_value ** argv)135 int CpuMeasureFilterTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
136 {
137     // reset indexMap_
138     indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
139 
140     if (rowCount_ <= 0) {
141         return SQLITE_OK;
142     }
143 
144     auto& cs = fc.GetConstraints();
145     for (size_t i = 0; i < cs.size(); i++) {
146         const auto& c = cs[i];
147         switch (c.col) {
148             case ID:
149                 FilterSorted(c.col, c.op, argv[i]);
150                 break;
151             case CPU:
152                 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])), cpuMeasureObj_.CpuData());
153                 break;
154             default:
155                 break;
156         }
157     }
158 
159     auto orderbys = fc.GetOrderBys();
160     for (auto i = orderbys.size(); i > 0;) {
161         i--;
162         switch (orderbys[i].iColumn) {
163             case ID:
164                 indexMap_->SortBy(orderbys[i].desc);
165                 break;
166             default:
167                 break;
168         }
169     }
170 
171     return SQLITE_OK;
172 }
173 
Column(int column) const174 int CpuMeasureFilterTable::Cursor::Column(int column) const
175 {
176     switch (column) {
177         case ID:
178             sqlite3_result_int64(context_, static_cast<int64_t>(cpuMeasureObj_.IdsData()[CurrentRow()]));
179             break;
180         case TYPE:
181             sqlite3_result_text(context_, "cpu_measure_filter", STR_DEFAULT_LEN, nullptr);
182             break;
183         case NAME: {
184             const std::string& str =
185                 dataCache_->GetDataFromDict(static_cast<size_t>(cpuMeasureObj_.NameData()[CurrentRow()]));
186             sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr);
187             break;
188         }
189         case CPU:
190             sqlite3_result_int64(context_, static_cast<int32_t>(cpuMeasureObj_.CpuData()[CurrentRow()]));
191             break;
192         default:
193             TS_LOGF("Unregistered column : %d", column);
194             break;
195     }
196     return SQLITE_OK;
197 }
198 
FilterSorted(int col,unsigned char op,sqlite3_value * argv)199 void CpuMeasureFilterTable::Cursor::FilterSorted(int col, unsigned char op, sqlite3_value* argv)
200 {
201     auto type = sqlite3_value_type(argv);
202     if (type != SQLITE_INTEGER) {
203         // other type consider it NULL, filter out nothing
204         indexMap_->Intersect(0, 0);
205         return;
206     }
207 
208     switch (col) {
209         case ID: {
210             auto v = static_cast<uint64_t>(sqlite3_value_int64(argv));
211             auto getValue = [](const uint32_t& row) {
212                 return row;
213             };
214             switch (op) {
215                 case SQLITE_INDEX_CONSTRAINT_EQ:
216                     indexMap_->IntersectabcEqual(cpuMeasureObj_.IdsData(), v, getValue);
217                     break;
218                 case SQLITE_INDEX_CONSTRAINT_GT:
219                     v++;
220                 case SQLITE_INDEX_CONSTRAINT_GE: {
221                     indexMap_->IntersectGreaterEqual(cpuMeasureObj_.IdsData(), v, getValue);
222                     break;
223                 }
224                 case SQLITE_INDEX_CONSTRAINT_LE:
225                     v++;
226                 case SQLITE_INDEX_CONSTRAINT_LT: {
227                     indexMap_->IntersectLessEqual(cpuMeasureObj_.IdsData(), v, getValue);
228                     break;
229                 }
230                 default:
231                     break;
232             } // end of switch (op)
233         } // end of case TS
234         default:
235             // can't filter, all rows
236             break;
237     }
238 }
239 } // namespace TraceStreamer
240 } // namespace SysTuning
241