• 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 "perf_thread_table.h"
17 
18 namespace SysTuning {
19 namespace TraceStreamer {
20 enum Index { ID = 0, THREAD_ID, PROCESS_ID, THREAD_NAME };
PerfThreadTable(const TraceDataCache * dataCache)21 PerfThreadTable::PerfThreadTable(const TraceDataCache* dataCache) : TableBase(dataCache)
22 {
23     tableColumn_.push_back(TableBase::ColumnInfo("id", "INTEGER"));
24     tableColumn_.push_back(TableBase::ColumnInfo("thread_id", "INTEGER"));
25     tableColumn_.push_back(TableBase::ColumnInfo("process_id", "INTEGER"));
26     tableColumn_.push_back(TableBase::ColumnInfo("thread_name", "TEXT"));
27     tablePriKey_.push_back("id");
28 }
29 
~PerfThreadTable()30 PerfThreadTable::~PerfThreadTable() {}
31 
EstimateFilterCost(FilterConstraints & fc,EstimatedIndexInfo & ei)32 void PerfThreadTable::EstimateFilterCost(FilterConstraints& fc, EstimatedIndexInfo& ei)
33 {
34     constexpr double filterBaseCost = 1000.0; // set-up and tear-down
35     constexpr double indexCost = 2.0;
36     ei.estimatedCost = filterBaseCost;
37 
38     auto rowCount = dataCache_->GetConstPerfThreadData().Size();
39     if (rowCount == 0 || rowCount == 1) {
40         ei.estimatedRows = rowCount;
41         ei.estimatedCost += indexCost * rowCount;
42         return;
43     }
44 
45     double filterCost = 0.0;
46     auto constraints = fc.GetConstraints();
47     if (constraints.empty()) { // scan all rows
48         filterCost = rowCount;
49     } else {
50         FilterByConstraint(fc, filterCost, rowCount);
51     }
52     ei.estimatedCost += filterCost;
53     ei.estimatedRows = rowCount;
54     ei.estimatedCost += rowCount * indexCost;
55 
56     ei.isOrdered = true;
57     auto orderbys = fc.GetOrderBys();
58     for (auto i = 0; i < orderbys.size(); i++) {
59         switch (orderbys[i].iColumn) {
60             case ID:
61                 break;
62             default: // other columns can be sorted by SQLite
63                 ei.isOrdered = false;
64                 break;
65         }
66     }
67 }
68 
FilterByConstraint(FilterConstraints & fc,double & filterCost,size_t rowCount)69 void PerfThreadTable::FilterByConstraint(FilterConstraints& fc, double& filterCost, size_t rowCount)
70 {
71     auto fcConstraints = fc.GetConstraints();
72     for (int32_t i = 0; i < static_cast<int32_t>(fcConstraints.size()); i++) {
73         if (rowCount <= 1) {
74             // only one row or nothing, needn't filter by constraint
75             filterCost += rowCount;
76             break;
77         }
78         const auto& c = fcConstraints[i];
79         switch (c.col) {
80             case ID: {
81                 if (CanFilterId(c.op, rowCount)) {
82                     fc.UpdateConstraint(i, true);
83                     filterCost += 1; // id can position by 1 step
84                 } else {
85                     filterCost += rowCount; // scan all rows
86                 }
87                 break;
88             }
89             default:                    // other column
90                 filterCost += rowCount; // scan all rows
91                 break;
92         }
93     }
94 }
95 
CreateCursor()96 std::unique_ptr<TableBase::Cursor> PerfThreadTable::CreateCursor()
97 {
98     return std::make_unique<Cursor>(dataCache_, this);
99 }
100 
Cursor(const TraceDataCache * dataCache,TableBase * table)101 PerfThreadTable::Cursor::Cursor(const TraceDataCache* dataCache, TableBase* table)
102     : TableBase::Cursor(dataCache, table, static_cast<uint32_t>(dataCache->GetConstPerfThreadData().Size())),
103       perfThreadObj_(dataCache->GetConstPerfThreadData())
104 {
105 }
106 
~Cursor()107 PerfThreadTable::Cursor::~Cursor() {}
108 
Filter(const FilterConstraints & fc,sqlite3_value ** argv)109 int32_t PerfThreadTable::Cursor::Filter(const FilterConstraints& fc, sqlite3_value** argv)
110 {
111     // reset indexMap_
112     indexMap_ = std::make_unique<IndexMap>(0, rowCount_);
113 
114     if (rowCount_ <= 0) {
115         return SQLITE_OK;
116     }
117 
118     auto& cs = fc.GetConstraints();
119     for (size_t i = 0; i < cs.size(); i++) {
120         const auto& c = cs[i];
121         switch (c.col) {
122             case ID:
123                 FilterId(c.op, argv[i]);
124                 break;
125             case THREAD_ID:
126                 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[i])), perfThreadObj_.Tids());
127                 break;
128             case PROCESS_ID:
129                 indexMap_->MixRange(c.op, static_cast<uint32_t>(sqlite3_value_int64(argv[i])), perfThreadObj_.Pids());
130                 break;
131             default:
132                 break;
133         }
134     }
135 
136     auto orderbys = fc.GetOrderBys();
137     for (auto i = orderbys.size(); i > 0;) {
138         i--;
139         switch (orderbys[i].iColumn) {
140             case ID:
141                 indexMap_->SortBy(orderbys[i].desc);
142                 break;
143             default:
144                 break;
145         }
146     }
147 
148     return SQLITE_OK;
149 }
150 
Column(int32_t column) const151 int32_t PerfThreadTable::Cursor::Column(int32_t column) const
152 {
153     switch (column) {
154         case ID:
155             sqlite3_result_int64(context_, static_cast<int32_t>(perfThreadObj_.IdsData()[CurrentRow()]));
156             break;
157         case THREAD_ID:
158             sqlite3_result_int64(context_, static_cast<int64_t>(perfThreadObj_.Tids()[CurrentRow()]));
159             break;
160         case PROCESS_ID:
161             sqlite3_result_int64(context_, static_cast<int64_t>(perfThreadObj_.Pids()[CurrentRow()]));
162             break;
163         case THREAD_NAME:
164             if (perfThreadObj_.ThreadNames()[CurrentRow()] != INVALID_UINT64) {
165                 auto threadNameIndex = static_cast<size_t>(perfThreadObj_.ThreadNames()[CurrentRow()]);
166                 if (dataCache_->GetDataFromDict(threadNameIndex).empty()) {
167                     break;
168                 }
169                 sqlite3_result_text(context_, dataCache_->GetDataFromDict(threadNameIndex).c_str(), STR_DEFAULT_LEN,
170                                     nullptr);
171             }
172             break;
173         default:
174             TS_LOGF("Unregistered column : %d", column);
175             break;
176     }
177     return SQLITE_OK;
178 }
179 } // namespace TraceStreamer
180 } // namespace SysTuning
181