• 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 "cpu_measure_filter_table.h"
17 
18 #include <cmath>
19 
20 namespace SysTuning {
21 namespace TraceStreamer {
22 enum class Index : int32_t { ID = 0, NAME, CPU };
CpuMeasureFilterTable(const TraceDataCache * dataCache)23 CpuMeasureFilterTable::CpuMeasureFilterTable(const TraceDataCache *dataCache) : TableBase(dataCache)
24 {
25     tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
26     tableColumn_.push_back(TableBase::ColumnInfo("name", "TEXT"));
27     tableColumn_.push_back(TableBase::ColumnInfo("cpu", "INTEGER"));
28     tablePriKey_.push_back("id");
29 }
30 
~CpuMeasureFilterTable()31 CpuMeasureFilterTable::~CpuMeasureFilterTable() {}
32 
FilterByConstraint(FilterConstraints & cpufc,double & cpufilterCost,size_t cpurowCount,uint32_t cpucurrenti)33 void CpuMeasureFilterTable::FilterByConstraint(FilterConstraints &cpufc,
34                                                double &cpufilterCost,
35                                                size_t cpurowCount,
36                                                uint32_t cpucurrenti)
37 {
38     // To use the EstimateFilterCost function in the TableBase parent class function to calculate the i-value of each
39     // for loop
40     const auto &cpuc = cpufc.GetConstraints()[cpucurrenti];
41     switch (static_cast<Index>(cpuc.col)) {
42         case Index::ID: {
43             auto cpuoldRowCount = cpurowCount;
44             if (CanFilterSorted(cpuc.op, cpurowCount)) {
45                 cpufc.UpdateConstraint(cpucurrenti, true);
46                 cpufilterCost += log2(cpuoldRowCount); // binary search
47             } else {
48                 cpufilterCost += cpuoldRowCount;
49             }
50             break;
51         }
52         default:                          // other column
53             cpufilterCost += cpurowCount; // scan all rows
54             break;
55     }
56 }
57 
CreateCursor()58 std::unique_ptr<TableBase::Cursor> CpuMeasureFilterTable::CreateCursor()
59 {
60     return std::make_unique<Cursor>(dataCache_, this);
61 }
62 
Cursor(const TraceDataCache * dataCache,TableBase * table)63 CpuMeasureFilterTable::Cursor::Cursor(const TraceDataCache *dataCache, TableBase *table)
64     : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstCpuMeasuresData().Size())),
65       cpuMeasureObj_(dataCache->GetConstCpuMeasuresData())
66 {
67 }
68 
~Cursor()69 CpuMeasureFilterTable::Cursor::~Cursor() {}
70 
Filter(const FilterConstraints & fc,sqlite3_value ** argv)71 int32_t CpuMeasureFilterTable::Cursor::Filter(const FilterConstraints &fc, sqlite3_value **argv)
72 {
73     // reset indexMap_
74     indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
75 
76     if (rowCount_ <= 0) {
77         return SQLITE_OK;
78     }
79 
80     auto &cpuMeasureFilterCs = fc.GetConstraints();
81     for (size_t i = 0; i < cpuMeasureFilterCs.size(); i++) {
82         const auto &c = cpuMeasureFilterCs[i];
83         switch (static_cast<Index>(c.col)) {
84             case Index::ID:
85                 FilterSorted(c.col, c.op, argv[i]);
86                 break;
87             case Index::CPU:
88                 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int(argv[i])), cpuMeasureObj_.CpuData());
89                 break;
90             default:
91                 break;
92         }
93     }
94 
95     auto cpuMeasureFilterTabOrderbys = fc.GetOrderBys();
96     for (auto i = cpuMeasureFilterTabOrderbys.size(); i > 0;) {
97         i--;
98         switch (static_cast<Index>(cpuMeasureFilterTabOrderbys[i].iColumn)) {
99             case Index::ID:
100                 indexMap_->SortBy(cpuMeasureFilterTabOrderbys[i].desc);
101                 break;
102             default:
103                 break;
104         }
105     }
106 
107     return SQLITE_OK;
108 }
109 
Column(int32_t column) const110 int32_t CpuMeasureFilterTable::Cursor::Column(int32_t column) const
111 {
112     switch (static_cast<Index>(column)) {
113         case Index::ID:
114             sqlite3_result_int64(context_, static_cast<int64_t>(cpuMeasureObj_.IdsData()[CurrentRow()]));
115             break;
116         case Index::NAME: {
117             const std::string &str =
118                 dataCache_->GetDataFromDict(static_cast<size_t>(cpuMeasureObj_.NameData()[CurrentRow()]));
119             sqlite3_result_text(context_, str.c_str(), STR_DEFAULT_LEN, nullptr);
120             break;
121         }
122         case Index::CPU:
123             sqlite3_result_int64(context_, static_cast<int32_t>(cpuMeasureObj_.CpuData()[CurrentRow()]));
124             break;
125         default:
126             TS_LOGF("Unregistered column : %d", column);
127             break;
128     }
129     return SQLITE_OK;
130 }
131 
FilterSorted(int32_t columns,unsigned char option,sqlite3_value * argv)132 void CpuMeasureFilterTable::Cursor::FilterSorted(int32_t columns, unsigned char option, sqlite3_value *argv)
133 {
134     auto valType = sqlite3_value_type(argv);
135     if (valType != SQLITE_INTEGER) {
136         // other valType consider it NULL, filter out nothing
137         indexMap_->Intersect(0, 0);
138         return;
139     }
140 
141     switch (static_cast<Index>(columns)) {
142         case Index::ID: {
143             auto v = static_cast<uint64_t>(sqlite3_value_int64(argv));
144             auto getValue = [](const uint32_t &row) { return row; };
145             switch (option) {
146                 case SQLITE_INDEX_CONSTRAINT_EQ:
147                     indexMap_->IntersectabcEqual(cpuMeasureObj_.IdsData(), v, getValue);
148                     break;
149                 case SQLITE_INDEX_CONSTRAINT_GT:
150                     v++;
151                 case SQLITE_INDEX_CONSTRAINT_GE: {
152                     indexMap_->IntersectGreaterEqual(cpuMeasureObj_.IdsData(), v, getValue);
153                     break;
154                 }
155                 case SQLITE_INDEX_CONSTRAINT_LE:
156                     v++;
157                 case SQLITE_INDEX_CONSTRAINT_LT: {
158                     indexMap_->IntersectLessEqual(cpuMeasureObj_.IdsData(), v, getValue);
159                     break;
160                 }
161                 default:
162                     break;
163             } // end of switch (option)
164         }     // end of case TS
165         default:
166             // can't filter, all rows
167             break;
168     }
169 }
GetOrbyes(FilterConstraints & cpufc,EstimatedIndexInfo & cpuei)170 void CpuMeasureFilterTable::GetOrbyes(FilterConstraints &cpufc, EstimatedIndexInfo &cpuei)
171 {
172     auto cpuorderbys = cpufc.GetOrderBys();
173     for (auto i = 0; i < cpuorderbys.size(); i++) {
174         switch (static_cast<Index>(cpuorderbys[i].iColumn)) {
175             case Index::ID:
176                 break;
177             default: // other columns can be sorted by SQLite
178                 cpuei.isOrdered = false;
179                 break;
180         }
181     }
182 }
183 } // namespace TraceStreamer
184 } // namespace SysTuning
185