1 /* 2 * Copyright (C) 2021 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 #ifndef SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_FLAT_SLICE_GENERATOR_H_ 18 #define SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_FLAT_SLICE_GENERATOR_H_ 19 20 #include "perfetto/ext/base/optional.h" 21 #include "src/trace_processor/sqlite/db_sqlite_table.h" 22 #include "src/trace_processor/storage/trace_storage.h" 23 24 namespace perfetto { 25 namespace trace_processor { 26 27 class TraceProcessorContext; 28 29 // Dynamic table generator for "flat slice" table. 30 // 31 // The concept of a "flat slice" is to take the data in the slice table and 32 // remove all notion of nesting; we do this by, at any point in time, taking the 33 // most specific active slice (i.e. the slice at the bottom of the stack) and 34 // representing that as the *only* slice that was running during that period. 35 // 36 // This concept becomes very useful when you try and linearise a trace and 37 // compare it with other traces spanning the same user action; "self time" (i.e. 38 // time spent in a slice but *not* any children) is easily computed and span 39 // joins with thread state become possible without limiting to only depth zero 40 // slices. 41 // 42 // This table also adds "gap slices" which fill in the gap between top level 43 // slices with a sentinal values so that comparision of the gap between slices 44 // is also possible. 45 // 46 // As input, this generator takes a start and end timestamp between 47 // which slices should be picked; we do this rather than just using the trace 48 // bounds so that the "gap slices" start and end at the appropriate place. 49 // 50 // Note that for the start bound we will *not* pick any slice which started 51 // before the bound even if it finished after. This is dissimilar to span join 52 // (which picks all slices with ts + dur >= bound) and is more akin to doing 53 // a simple ts >= bound. However, slices *will* be truncated at the end 54 // if they would spill past the provided end bound. 55 class ExperimentalFlatSliceGenerator 56 : public DbSqliteTable::DynamicTableGenerator { 57 public: 58 ExperimentalFlatSliceGenerator(TraceProcessorContext* context); 59 60 Table::Schema CreateSchema() override; 61 std::string TableName() override; 62 uint32_t EstimateRowCount() override; 63 base::Status ValidateConstraints(const QueryConstraints&) override; 64 base::Status ComputeTable(const std::vector<Constraint>& cs, 65 const std::vector<Order>& ob, 66 const BitVector& cols_used, 67 std::unique_ptr<Table>& table_return) override; 68 69 // Visibile for testing. 70 static std::unique_ptr<tables::ExperimentalFlatSliceTable> 71 ComputeFlatSliceTable(const tables::SliceTable&, 72 StringPool*, 73 int64_t start_bound, 74 int64_t end_bound); 75 76 private: 77 TraceProcessorContext* context_ = nullptr; 78 }; 79 80 } // namespace trace_processor 81 } // namespace perfetto 82 83 #endif // SRC_TRACE_PROCESSOR_DYNAMIC_EXPERIMENTAL_FLAT_SLICE_GENERATOR_H_ 84