Coverage Report

Created: 2026-05-09 09:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
be/src/util/block_budget.h
Line
Count
Source
1
// Licensed to the Apache Software Foundation (ASF) under one
2
// or more contributor license agreements.  See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership.  The ASF licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License.  You may obtain a copy of the License at
8
//
9
//   http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied.  See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
#pragma once
19
20
#include <algorithm>
21
#include <cstddef>
22
23
namespace doris {
24
25
// Lightweight value type that captures the dual row+byte budget for block
26
// output sizing.  Every operator that needs to respect the adaptive batch
27
// size feature can construct a BlockBudget from RuntimeState's batch_size()
28
// and preferred_block_size_bytes() and use the helper methods instead of
29
// reimplementing the same row/byte logic inline.
30
//
31
// Typical usage:
32
//   BlockBudget budget(state->batch_size(), state->preferred_block_size_bytes());
33
//   size_t eff = budget.effective_max_rows(estimated_row_bytes);
34
//   while (budget.within_budget(block.rows(), block.bytes())) { ... }
35
//
36
struct BlockBudget {
37
    size_t max_rows;
38
    size_t max_bytes; // byte budget from preferred_block_size_bytes(), 0 means disabled
39
40
2.79M
    BlockBudget(size_t max_rows_, size_t max_bytes_) : max_rows(max_rows_), max_bytes(max_bytes_) {}
41
42
    // Pre-compute effective row limit from an estimated average row byte size.
43
    // When max_bytes == 0 or estimated_row_bytes == 0, returns max_rows.
44
    // Always returns at least 1.
45
    size_t effective_max_rows(size_t estimated_row_bytes) const {
46
        if (max_bytes > 0 && estimated_row_bytes > 0) {
47
            size_t bytes_limit = max_bytes / estimated_row_bytes;
48
            return std::max(size_t(1), std::min(max_rows, bytes_limit));
49
        }
50
        return max_rows;
51
    }
52
53
    // Check if a block with the given rows/bytes is still within budget.
54
    // Use this in loop *continuation* conditions (while/for).
55
    bool within_budget(size_t rows, size_t bytes) const {
56
        return rows < max_rows && (max_bytes == 0 || bytes < max_bytes);
57
    }
58
59
    // Check if a block with the given rows/bytes has exceeded the budget.
60
    // Use this in loop *break* conditions.
61
7.83k
    bool exceeded(size_t rows, size_t bytes) const {
62
7.83k
        return rows >= max_rows || (max_bytes > 0 && bytes >= max_bytes);
63
7.83k
    }
64
65
    // Compute how many more rows can be added to a block that currently
66
    // has current_rows rows and current_bytes bytes, respecting both the
67
    // row cap and the byte budget.
68
    // The 3-arg overload accepts an explicit estimated_row_bytes (useful when
69
    // the estimate comes from a different source, e.g. a child block).
70
    // The 2-arg overload derives the estimate from current_bytes / current_rows.
71
    // Returns 0 when the block is already at or over budget.
72
    size_t remaining_rows(size_t current_rows, size_t current_bytes,
73
                          size_t estimated_row_bytes) const {
74
        size_t row_capacity = (current_rows < max_rows) ? (max_rows - current_rows) : 0;
75
        if (max_bytes > 0 && estimated_row_bytes > 0) {
76
            if (current_bytes >= max_bytes) {
77
                return 0;
78
            }
79
            size_t byte_capacity = (max_bytes - current_bytes) / estimated_row_bytes;
80
            row_capacity = std::min(row_capacity, byte_capacity);
81
        }
82
        return row_capacity;
83
    }
84
85
    size_t remaining_rows(size_t current_rows, size_t current_bytes) const {
86
        size_t estimated =
87
                (current_rows > 0 && current_bytes > 0) ? (current_bytes / current_rows) : 0;
88
        return remaining_rows(current_rows, current_bytes, estimated);
89
    }
90
};
91
92
} // namespace doris