| /* |
| * Copyright (C) 2026 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_PLUGINS_FLAMECHART_FLAMECHART_H_ |
| #define SRC_TRACE_PROCESSOR_PLUGINS_FLAMECHART_FLAMECHART_H_ |
| |
| #include <cstdint> |
| |
| #include "perfetto/ext/base/status_or.h" |
| #include "src/trace_processor/containers/string_pool.h" |
| #include "src/trace_processor/core/dataframe/dataframe.h" |
| #include "src/trace_processor/core/tree/tree.h" |
| #include "src/trace_processor/core/util/span.h" |
| |
| namespace perfetto::trace_processor::flamechart { |
| |
| // Computes the flame-chart rectangle set from a stack tree and a series of |
| // sample points. |
| // |
| // The tree encodes the stack structure: `tree.parent` links each node to its |
| // caller (row indices, kNullParent for roots, parents before children). Each |
| // point is a (ts[i], leaf_id[i]) pair: a sample timestamp and the tree node |
| // of the innermost (leaf) frame at that time. |ts| must be non-decreasing and |
| // the two spans must have equal size. Leaf ids are original node ids (e.g. a |
| // callsite id), resolved through the id -> row index persisted on the tree by |
| // core::BuildTree; for trees without an id column the ids are row indices. |
| // Unresolvable leaves are skipped: open segments are kept as-is and the gap |
| // does not contribute to sample counts. |
| // |
| // The returned dataframe has five columns, in this order: |
| // 0: ts - segment start timestamp |
| // 1: dur - segment duration, or -1 if still open at the last point |
| // 2: depth - stack depth (0 = outermost/root frame) |
| // 3: id - original node id of the segment's frame (the tree's id |
| // column), so runs join directly against the tree's source table; row |
| // index for trees without an id column |
| // 4: sample_count - number of points in the segment |
| // |
| // The output is the maximal-run (prefix-merge) decomposition: for each depth, |
| // a segment spans the time range over which the same frame was continuously |
| // present at that depth. Consecutive points sharing a stack prefix extend the |
| // shared segments; only divergent depths open new segments. This keeps the |
| // output far below (points x depth): the leaf depth yields about one segment |
| // per run while shallow depths yield only a handful. Segments still open |
| // after the last point have duration -1 (incomplete). Zero-duration segments |
| // from stack transitions at equal timestamps are omitted. |
| // |
| // The sweep is a single pass over the points. Each point walks its stack and |
| // updates counts at every depth, so time is O(sum of sample stack depths). |
| // Memory is O(maximum stack depth) plus the emitted output. |
| base::StatusOr<dataframe::Dataframe> Build(const core::Tree& tree, |
| core::Span<const int64_t> ts, |
| core::Span<const int64_t> leaf_id, |
| StringPool* pool); |
| |
| } // namespace perfetto::trace_processor::flamechart |
| |
| #endif // SRC_TRACE_PROCESSOR_PLUGINS_FLAMECHART_FLAMECHART_H_ |