Skip to content

Commit 4eec006

Browse files
committed
tp: have the executor end every step's run when its stream ends
**Why** A step let go of what it held only if it remembered to clear itself, and almost none did. GraphTree, the interval operators and the tree transforms kept everything they built until the next run. One `OperatorState` mixed per-call scratch, rows held for the whole input and the step's status, so nothing said what a step may keep or for how long. **Changes** - `operator.h` states the rules every step keeps to. Each field of a state declares its lifetime: `Held<T>` or `RunValue<T>` for the run, `CallScratch<T>` for one call, and anything else is set when the state is made. - `Held<T>` and `RunValue<T>` register with their state. The pipeline ends their run as soon as the step's stream ends, and again before a source is restarted. `Reset()` and `ResetEachRun` are gone. - States are made once and reused, because the same pipeline is often rerun for small queries. Ending a run keeps up to 64 KiB of each container's storage and releases anything larger. - The pipeline merges its states' registries by segment, so ending a run is one pass with no call per state. - A batch a step outputs never points into its state, so a run can end while its batches are still read. `GroupedSort` copies its group numbers into a buffer instead of lending them. - Each state's fields are grouped by what they do. **Results** `INCLUDE` of `heap_graph_dominator_tree` on `test/data/heap_graph_object_for_benchmarks.pftrace`, release build: | | Peak RSS | Buffers | |---|---:|---:| | #8331 | 305 MB | 57 MB | | This PR | 270 MB | 53 MB | Every heap graph table is byte-identical. Rerunning a one-row pipeline costs about 2-3 ns more per step that holds state. Large runs are unchanged. **Testing** - New `StateTest.AStepsRunEndsWithItsStream`. - The affected unit test suites pass.
1 parent a4314bd commit 4eec006

64 files changed

Lines changed: 934 additions & 450 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎BUILD‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2688,6 +2688,7 @@ perfetto_filegroup(
26882688
"src/trace_processor/core/exec/row_cursor.h",
26892689
"src/trace_processor/core/exec/row_store.cc",
26902690
"src/trace_processor/core/exec/row_store.h",
2691+
"src/trace_processor/core/exec/run_held.h",
26912692
"src/trace_processor/core/exec/selection.cc",
26922693
"src/trace_processor/core/exec/selection.h",
26932694
"src/trace_processor/core/exec/sort.cc",

‎src/trace_processor/core/exec/BUILD.gn‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ source_set("exec") {
7878
"row_cursor.h",
7979
"row_store.cc",
8080
"row_store.h",
81+
"run_held.h",
8182
"selection.cc",
8283
"selection.h",
8384
"sort.cc",

‎src/trace_processor/core/exec/aggregate_function.cc‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "perfetto/ext/base/utils.h"
2626
#include "src/trace_processor/core/common/storage_types.h"
2727
#include "src/trace_processor/core/exec/column_chunk.h"
28+
#include "src/trace_processor/core/exec/run_held.h"
2829

2930
namespace perfetto::trace_processor::core::exec {
3031

@@ -90,6 +91,11 @@ uint8_t* SeenBytes::For(uint32_t groups, bool nulls) {
9091
return bytes_.data();
9192
}
9293

94+
void SeenBytes::EndRun() {
95+
Clear();
96+
EndRunOf(&bytes_);
97+
}
98+
9399
void SeenBytes::Clear() {
94100
bytes_.clear();
95101
tracking_ = false;

‎src/trace_processor/core/exec/aggregate_function.h‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "src/trace_processor/core/exec/column_view.h"
2525
#include "src/trace_processor/core/exec/context.h"
2626
#include "src/trace_processor/core/exec/operator.h"
27+
#include "src/trace_processor/core/exec/run_held.h"
2728
#include "src/trace_processor/core/exec/selection.h"
2829
#include "src/trace_processor/core/util/bit_vector.h"
2930
#include "src/trace_processor/core/util/flex_vector.h"
@@ -71,6 +72,12 @@ class AggregateInputLoader {
7172
uint32_t count,
7273
AggregateInput* out);
7374

75+
// Ends a run (see RunHeld).
76+
void EndRun() {
77+
EndRunOf(&values_);
78+
EndRunOf(&valid_);
79+
}
80+
7481
private:
7582
FlexVector<int64_t> values_;
7683
FlexVector<uint64_t> valid_;
@@ -96,6 +103,8 @@ class SeenBytes {
96103
// groups in all, whose input holds nulls if `nulls`.
97104
uint8_t* For(uint32_t groups, bool nulls);
98105
void Clear();
106+
// Clear(), keeping only small allocations for the next run (see RunHeld).
107+
void EndRun();
99108

100109
private:
101110
FlexVector<uint8_t> bytes_;

‎src/trace_processor/core/exec/assert_type.cc‎

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,6 @@ base::Status AssertType::status(const OperatorState& state) const {
175175
return state.Cast<const State>().status;
176176
}
177177

178-
void AssertType::State::Reset() {
179-
status = base::OkStatus();
180-
}
181-
182178
bool AssertType::Widen(const ColumnView& column,
183179
const Selection& selection,
184180
ColumnChunk& chunk,

‎src/trace_processor/core/exec/assert_type.h‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "src/trace_processor/core/exec/context.h"
3030
#include "src/trace_processor/core/exec/operator.h"
3131
#include "src/trace_processor/core/exec/row_batch.h"
32+
#include "src/trace_processor/core/exec/run_held.h"
3233

3334
namespace perfetto::trace_processor::core::exec {
3435

@@ -61,12 +62,11 @@ class AssertType final : public Transform {
6162
friend class PipelineFormatter;
6263

6364
struct State : OperatorState {
64-
explicit State(Context& c) : OperatorState(ResetEachRun{}), context(&c) {}
65+
explicit State(Context& c) : context(&c) {}
6566
~State() override;
66-
void Reset() override;
6767
// What the converted column is written in.
6868
Context* context;
69-
base::Status status = base::OkStatus();
69+
Held<base::Status> status{this};
7070
};
7171

7272
bool Widen(const ColumnView&, const Selection&, ColumnChunk&, State&) const;

‎src/trace_processor/core/exec/batch_buffer.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ class BatchBuffer {
4444
column.nullable = false;
4545
}
4646
}
47+
// Ends a run (see RunHeld): the buffers go back to the pool.
48+
void EndRun() { Clear(); }
4749

4850
private:
4951
struct Column {

‎src/trace_processor/core/exec/breaker.cc‎

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,6 @@ OpResult Breaker::Finish(RowBatch& out, OperatorState& state) const {
6060
return s.status.ok() ? OpResult::kNeedMoreInput : OpResult::kError;
6161
}
6262

63-
void Breaker::State::Reset() {
64-
status = base::OkStatus();
65-
filled = false;
66-
}
67-
6863
base::Status Breaker::status(const OperatorState& state) const {
6964
const State& s = state.Cast<const State>();
7065
return s.status;

‎src/trace_processor/core/exec/breaker.h‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "perfetto/base/status.h"
2323
#include "src/trace_processor/core/exec/operator.h"
2424
#include "src/trace_processor/core/exec/row_batch.h"
25+
#include "src/trace_processor/core/exec/run_held.h"
2526

2627
namespace perfetto::trace_processor::core::exec {
2728

@@ -31,14 +32,15 @@ namespace perfetto::trace_processor::core::exec {
3132
class Breaker : public Operator {
3233
public:
3334
struct State : OperatorState {
34-
State() : OperatorState(ResetEachRun{}) {}
35+
State() = default;
3536
~State() override;
36-
void Reset() override;
3737

38-
base::Status status = base::OkStatus();
39-
bool filled = false;
4038
// What the columns served are filled in.
4139
Context* context = nullptr;
40+
41+
Held<base::Status> status{this};
42+
// Whether Finalize() has run.
43+
RunValue<bool> filled{this, false};
4244
};
4345

4446
~Breaker() override;

‎src/trace_processor/core/exec/breaker_benchmark.cc‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ void Run(benchmark::State& state,
7070
while (op.Finish(out, *op_state) == OpResult::kHaveMoreOutput) {
7171
benchmark::DoNotOptimize(out.size());
7272
}
73-
op_state->Reset();
73+
op_state->EndRun();
7474
}
7575
state.SetItemsProcessed(static_cast<int64_t>(state.iterations()) * rows);
7676
}

0 commit comments

Comments
 (0)