/* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SRC_TRACE_PROCESSOR_SORTER_TRACE_SORTER_H_ #define SRC_TRACE_PROCESSOR_SORTER_TRACE_SORTER_H_ #include <algorithm> #include <cstddef> #include <cstdint> #include <limits> #include <memory> #include <optional> #include <string> #include <tuple> #include <type_traits> #include <utility> #include <vector> #include "perfetto/base/logging.h" #include "perfetto/ext/base/circular_queue.h" #include "perfetto/public/compiler.h" #include "perfetto/trace_processor/ref_counted.h" #include "perfetto/trace_processor/trace_blob_view.h" #include "src/trace_processor/importers/android_bugreport/android_log_event.h" #include "src/trace_processor/importers/common/parser_types.h" #include "src/trace_processor/importers/common/trace_parser.h" #include "src/trace_processor/importers/fuchsia/fuchsia_record.h" #include "src/trace_processor/importers/instruments/row.h" #include "src/trace_processor/importers/perf/record.h" #include "src/trace_processor/importers/systrace/systrace_line.h" #include "src/trace_processor/sorter/trace_token_buffer.h" #include "src/trace_processor/storage/trace_storage.h" #include "src/trace_processor/types/trace_processor_context.h" #include "src/trace_processor/util/bump_allocator.h" namespace perfetto::trace_processor { // This class takes care of sorting events parsed from the trace stream in // arbitrary order and pushing them to the next pipeline stages (parsing) in // order. In order to support streaming use-cases, sorting happens within a // window. // // Events are held in the TraceSorter staging area (events_) until either: // 1. We can determine that it's safe to extract events by observing // TracingServiceEvent Flush and ReadBuffer events // 2. The trace EOF is reached // // Incremental extraction // // Incremental extraction happens by using a combination of flush and read // buffer events from the tracing service. Note that incremental extraction // is only applicable for write_into_file traces; ring-buffer traces will // be sorted fully in-memory implicitly because there is only a single read // buffer call at the end. // // The algorithm for incremental extraction is explained in detail at // go/trace-sorting-is-complicated. // // Sorting algorithm // // The sorting algorithm is designed around the assumption that: // - Most events come from ftrace. // - Ftrace events are sorted within each cpu most of the times. // // Due to this, this class is oprerates as a streaming merge-sort of N+1 queues // (N = num cpus + 1 for non-ftrace events). Each queue in turn gets sorted (if // necessary) before proceeding with the global merge-sort-extract. // // When an event is pushed through, it is just appended to the end of one of // the N queues. While appending, we keep track of the fact that the queue // is still ordered or just lost ordering. When an out-of-order event is // detected on a queue we keep track of: (1) the offset within the queue where // the chaos begun, (2) the timestamp that broke the ordering. // // When we decide to extract events from the queues into the next stages of // the trace processor, we re-sort the events in the queue. Rather than // re-sorting everything all the times, we use the above knowledge to restrict // sorting to the (hopefully smaller) tail of the |events_| staging area. // At any time, the first partition of |events_| [0 .. sort_start_idx_) is // ordered, and the second partition [sort_start_idx_.. end] is not. // We use a logarithmic bound search operation to figure out what is the index // within the first partition where sorting should start, and sort all events // from there to the end. class TraceSorter { … }; } // namespace perfetto::trace_processor #endif // SRC_TRACE_PROCESSOR_SORTER_TRACE_SORTER_H_