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_PRELUDE_TABLE_FUNCTIONS_EXPERIMENTAL_FLAT_SLICE_H_ 18 #define SRC_TRACE_PROCESSOR_PRELUDE_TABLE_FUNCTIONS_EXPERIMENTAL_FLAT_SLICE_H_ 19 20 #include <optional> 21 22 #include "src/trace_processor/prelude/table_functions/table_function.h" 23 #include "src/trace_processor/storage/trace_storage.h" 24 25 namespace perfetto { 26 namespace trace_processor { 27 28 class TraceProcessorContext; 29 30 // Dynamic table generator for "flat slice" table. 31 // 32 // The concept of a "flat slice" is to take the data in the slice table and 33 // remove all notion of nesting; we do this by, at any point in time, taking the 34 // most specific active slice (i.e. the slice at the bottom of the stack) and 35 // representing that as the *only* slice that was running during that period. 36 // 37 // This concept becomes very useful when you try and linearise a trace and 38 // compare it with other traces spanning the same user action; "self time" (i.e. 39 // time spent in a slice but *not* any children) is easily computed and span 40 // joins with thread state become possible without limiting to only depth zero 41 // slices. 42 // 43 // This table also adds "gap slices" which fill in the gap between top level 44 // slices with a sentinal values so that comparision of the gap between slices 45 // is also possible. 46 // 47 // As input, this generator takes a start and end timestamp between 48 // which slices should be picked; we do this rather than just using the trace 49 // bounds so that the "gap slices" start and end at the appropriate place. 50 // 51 // Note that for the start bound we will *not* pick any slice which started 52 // before the bound even if it finished after. This is dissimilar to span join 53 // (which picks all slices with ts + dur >= bound) and is more akin to doing 54 // a simple ts >= bound. However, slices *will* be truncated at the end 55 // if they would spill past the provided end bound. 56 class ExperimentalFlatSlice : public TableFunction { 57 public: 58 ExperimentalFlatSlice(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_PRELUDE_TABLE_FUNCTIONS_EXPERIMENTAL_FLAT_SLICE_H_ 84