1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "src/trace_processor/slice_table.h" 18 19 #include "src/trace_processor/storage_columns.h" 20 21 namespace perfetto { 22 namespace trace_processor { 23 24 SliceTable::SliceTable(sqlite3*, const TraceStorage* storage) 25 : storage_(storage) {} 26 27 void SliceTable::RegisterTable(sqlite3* db, const TraceStorage* storage) { 28 Table::Register<SliceTable>(db, storage, "internal_slice"); 29 } 30 31 StorageSchema SliceTable::CreateStorageSchema() { 32 const auto& slices = storage_->nestable_slices(); 33 return StorageSchema::Builder() 34 .AddGenericNumericColumn("slice_id", RowAccessor()) 35 .AddOrderedNumericColumn("ts", &slices.start_ns()) 36 .AddNumericColumn("dur", &slices.durations()) 37 .AddNumericColumn("ref", &slices.refs()) 38 .AddStringColumn("ref_type", &slices.types(), &GetRefTypeStringMap()) 39 .AddStringColumn("cat", &slices.cats(), &storage_->string_pool()) 40 .AddStringColumn("name", &slices.names(), &storage_->string_pool()) 41 .AddNumericColumn("depth", &slices.depths()) 42 .AddNumericColumn("stack_id", &slices.stack_ids()) 43 .AddNumericColumn("parent_stack_id", &slices.parent_stack_ids()) 44 .Build({"slice_id"}); 45 } 46 47 uint32_t SliceTable::RowCount() { 48 return static_cast<uint32_t>(storage_->nestable_slices().slice_count()); 49 } 50 51 int SliceTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) { 52 info->estimated_cost = EstimateCost(qc); 53 54 // Only the string columns are handled by SQLite 55 info->order_by_consumed = true; 56 size_t name_index = schema().ColumnIndexFromName("name"); 57 size_t cat_index = schema().ColumnIndexFromName("cat"); 58 size_t ref_type_index = schema().ColumnIndexFromName("ref_type"); 59 for (size_t i = 0; i < qc.constraints().size(); i++) { 60 auto col = static_cast<size_t>(qc.constraints()[i].iColumn); 61 info->omit[i] = 62 col != name_index && col != cat_index && col != ref_type_index; 63 } 64 return SQLITE_OK; 65 } 66 67 uint32_t SliceTable::EstimateCost(const QueryConstraints& qc) { 68 // slice_id is row index, so we can filter efficiently for equality. 69 if (HasEqConstraint(qc, "slice_id")) 70 return 1; 71 72 auto eq_ts = HasEqConstraint(qc, "ts"); 73 auto eq_ref = HasEqConstraint(qc, "ref"); 74 auto eq_ref_type = HasEqConstraint(qc, "ref_type"); 75 auto eq_depth = HasEqConstraint(qc, "depth"); 76 auto eq_name = HasEqConstraint(qc, "name"); 77 78 // ref + ref_type + ts + depth is a unique key. others are estimates. 79 if (eq_ref && eq_ref_type && eq_ts && eq_depth) 80 return 1; 81 else if (eq_ref && eq_ref_type && eq_ts) 82 return 10; 83 else if (eq_ts && eq_name) 84 return 10; 85 else if (eq_ts || eq_name) 86 return 100; 87 return RowCount(); 88 } 89 90 } // namespace trace_processor 91 } // namespace perfetto 92