This is an automated email from the ASF dual-hosted git repository.

morningman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new b9ee837a3e6 [opt](build) Enable unity builds for the remaining BE 
targets (#66789)
b9ee837a3e6 is described below

commit b9ee837a3e691e6354dfdc8e1a550d8fca4d3409
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Sun Aug 16 12:48:31 2026 +0800

    [opt](build) Enable unity builds for the remaining BE targets (#66789)
    
    > Part of the BE build-time optimization series tracked in #66715.
    >
    > Split out of **https://github.com/apache/doris/pull/66510**, which
    carries the whole
    > BE build-time batch. #66712 introduced the `ENABLE_UNITY_BUILD` switch
    and piloted
    > unity builds on three low-risk glue targets; #66776 extended it to
    Exec and Exprs.
    > This PR finishes the line: unity builds for every remaining BE target
    where it
    > helps, plus a fail-loud guard for the skip lists. It is the last PR of
    the unity
    > sub-series (the remaining two PRs of the batch are orthogonal:
    extern-template
    > convergence and olap_common decoupling).
    
    ### What problem does this PR solve?
    
    Related PR: #66510, #66712, #66776
    
    Problem Summary:
    
    Same mechanism as #66712/#66776: most of the cold-build cost of
    glue-heavy targets
    is **re-parsing the shared header closure once per small `.cpp`**, and
    CMake's
    `UNITY_BUILD` makes a batch pay that parse once. This PR applies it to
    the twelve
    remaining targets where the win is real, and writes down (in-tree) the
    two places
    where it is not.
    
    The eleven commits, in fix-then-enable pairs:
    
    1. **Deduplicate cloud/storage file-scope names that clash under unity**
    —
    identical copies hoisted to one shared definition (warm-up metric window
       spans -> `bvar_windowed_adder.h`; the "D0R1" segment footer magic ->
    `segment/common.h`; the `path_allocated_bytes` PathInData accounting
    helper
    that #66204 landed in two variant v2 TUs -> `util/json/path_in_data.h`),
    a
       divergent copy renamed instead (`create_ext_meta_io_context` keeps
    file-cache stats where its siblings reset them); **plus one real latent
       bug**: `merger.cpp` threw with `INTERNAL_ERROR` bound to
    `PPlanFragmentCancelReason::INTERNAL_ERROR` (=3) from `types.pb.h`
    instead
    of `ErrorCode::INTERNAL_ERROR` (=6) — no `ErrorCode` using-directive was
    in
    scope. Qualified; those compaction-failure statuses now carry the
    intended
       code.
    2. **Unity for Cloud (batch 12) and Storage target-wide (batch 12)** —
    Storage's
    previous index/-only inverse-selection flips to graded opt-outs. Cloud:
    37
       members -> 4 batches. Storage: 232 members -> 20 batches.
    3. **Deduplicate format_v2 file-scope helpers** that clash under unity.
    4. **Unity for the format_v2 half of Format (batch 8)** — the v1
    `format/` tree is
    slated for removal, so every v1 file stays individual rather than paying
    the
       v1/v2 twin-symbol dedup a joint unity would need.
    5. **Resolve runtime/load/io/util file-scope clashes** — including two
    more latent
    bugs found by merged TUs: `column_predicate.h` had the same unqualified
    `INTERNAL_ERROR` mis-binding as `merger.cpp`, and `vdatetime_value.h`
    defined a
    `static RE2` in the header (one RE2 construction per including TU at
    startup;
    now a C++17 inline variable, one program-wide). `runtime_profile.h` also
       carried two never-referenced private fields; removed.
    6. **Unity for Runtime, Load, IO and Util** (batch 12/12/16/24 by member
    weight).
    7. **Add missing include guards to two more headers**
    (`cgroup_cpu_ctl.h`,
    `complex_type_deserialize_util.h`) — found the same way as the two in
    #66776.
    8. **Unity for Core, Agent, Udf, Common, ann_index** — and the Service
    negative
       result recorded in-tree (see below).
    9. **Unity for the thrift half of DorisGen (batch 8)** — protobuf `.cc`
    files stay
       individual structurally: protoc emits identical file-scope statics
       (`schemas[]`, `file_default_instances[]`) in every one.
    10. **Evict `file_cache_lru_tool.cpp` from `libIO.a`** — a standalone
    tool with its
    own `main()` must not be an archive member once unity can merge it into
    an
        object the `doris_be` link actually pulls in.
    11. **Fail the configure when a unity skip entry goes stale** —
    `set_source_files_properties()` silently ignores nonexistent paths, so a
    rename would quietly dissolve a skip entry and the file would rejoin its
    batch with no diagnostic. All thirteen skip lists (including the merged
    Exec/Exprs and pilot ones) now go through
    `doris_skip_unity_inclusion()`,
    which FATAL_ERRORs on a nonexistent entry (generated `GENSRC_DIR` paths
        exempt — they legitimately do not exist on a fresh configure).
    
    ### Benefit
    
    Measured on the development branch this series is split from (arm64
    macOS,
    clang 20, `-j14`, PCH on, cold builds, same-machine paired runs):
    
    - this wave (on top of the #66776 state): **7m57s -> 6m18s (-99s /
    -20.7%)**,
      sum-of-TU CPU (user) 98.7 -> 76.7 min, compile units 7810 -> 7280.
    - static archives collapse as duplicate DWARF / weak-template copies
    merge
    (measured on this branch, unity OFF vs ON): libStorage.a 1592 -> 514 MB,
      libCloud.a 441 -> 107 MB, libRuntime.a 356 -> 122 MB, libLoad.a 311 ->
      100 MB, libFormat.a 1057 -> 760 MB, libCore.a 371 -> 182 MB. Less disk
      thrash per build, faster archiving and linking.
    - the four latent bugs above found and fixed (two of them wrong-code).
    
    ### Verification on this branch (arm64 macOS, clang 20, ENABLE_PCH=ON)
    
    - unity=ON full build: zero failures across all 7927 TUs, `doris_be`
    links
    (319 MB). One upstream-drift clash surfaced and fixed first (the #66204
      `path_allocated_bytes` twins — folded into the dedup commit).
    - unity coverage after this PR: 110 batches / 1224 member files
    tree-wide, of
    which this PR adds 63 batches / 696 members (per-target counts in the
    commit
      messages); `compile_commands.json` agrees.
    - `ENABLE_UNITY_BUILD=OFF` reconfigure: unity entries drop to zero and
    the TU
    count goes 7927 -> 9041 = exactly the 110 batches dissolving into their
    1224
    members; full rebuild green, `doris_be` relinks -> the switch's blast
    radius
      is precisely the unity config.
    - BE UT (`BUILD_TYPE_UT=Debug`): doris_be_test compiles and links clean
    — this
    specifically exercises the four "a test #includes the src .cpp" opt-outs
    below.
    - fail-loud helper: deliberately renaming one skip entry makes the
    configure
    fail with `unity skip entry does not exist (renamed or moved?): <path>`
    and
      the offending CMakeLists line; reverting restores a clean configure.
    
    ### First CI round: two reds, both root-caused and fixed in-tree
    
    - **ASAN Compile**: libstdc++-15 annotates loops in its own headers with
    `#pragma GCC unroll`; under `-O1` + sanitizers + coverage the unroller
    punts
    and clang's `-Wpass-failed` (a missed-*hint* diagnostic with no
    correctness
    signal) became fatal under `-Werror` once a storage unity batch changed
    the
      emission context. Fixed by `-Wno-pass-failed` for clang tree-wide.
    - **BE UT**: `FSFileCacheLeakCleanerTest.remove_orphan_and_tmp_files` —
    a
    pre-existing test-helper race: it waited for the meta-store *write
    queue* to
    drain, but the async worker dequeues before it issues the rocksdb Put,
    so
    the leak scan could still count zero metadata blocks and skip cleanup.
    The
    unity-batched IO objects shifted thread timing on the ASAN runner and
    hit
    the window (this test's only failure in its last 40 CI runs is this PR's
    round — the race is upstream, the timing shift is ours). Fixed by
    polling
      the store itself instead of the queue size.
    
    ### Deliberate opt-outs (not omissions)
    
    - **Per-file opt-outs** (~50 files across the targets, each annotated in
    its
    CMakeLists): file-scope macro leakers, the heaviest
    template-instantiation TUs
      (so no batch inherits their weight), `ENABLE_VARIANT_NESTED_GROUP` /
    `ENABLE_TDE` module swaps (unaudited out-of-tree sources), and generated
      protobuf `.cc`.
    - **Four files a test compiles a second time by `#include`-ing the
    .cpp**
    (`storage/compaction/collection_statistics.cpp`,
    `runtime/descriptors.cpp`,
    `core/column/column_variant.cpp`,
    `core/data_type/convert_field_to_type.cpp`):
    the test object must shadow a never-pulled archive member, but a unity
    batch
    is pulled in for its siblings and the linker sees a duplicate
    definition.
    Same failure class the first CI round of #66776 hit; this time the whole
    tree
    was swept up front (`grep -rn '#include ".*\.cpp"' be/test`) and the
    remaining
    hits are either already opted out, structurally outside unity scope, or
      test-side files.
    - **Service stays at http-only unity**: widening to the whole target at
    batch 8
    was tried and measured **slower** (service segment slot time 104s ->
    132s) —
    splitting the single http jumbo repays the shared-closure parse per
    batch and
    the heterogeneous non-http TUs gain too little to cover it. The
    CMakeLists
      comment records this so nobody retries it blind.
    - **contrib (openblas/clucene) deliberately untouched**: openblas is f2c
    output —
    2055 files with colliding `static c__1` file-scope constants,
    structurally
      un-unifiable.
    
    ### Cross-platform note (please watch the gcc pipeline)
    
    All local verification is macOS/clang. gcc-only hazards were audited up
    front:
    the `-Wsubobject-linkage` pattern that bit #66776 (an
    anonymous-namespace type as
    a member of an external-linkage class turns into an error only once
    unity makes
    the file `#include`-d) was swept across all 627 files entering unity
    scope —
    every anonymous-namespace type usage found is function-local, so no
    hazard — but
    the sweep is heuristic, so the first Performance (gcc) CI round is worth
    watching.
    
    ### Release note
    
    None
    
    ### Check List (For Author)
    
    - Test
        - [x] Manual test (add detailed scripts or steps below)
    - Full BE build with unity ON: all 7927 TUs green, `doris_be` links.
            - `ENABLE_UNITY_BUILD=OFF` reconfigure + full rebuild green; TU
    accounting closes exactly (7927 -> 9041); flip back ON restores.
    - BE UT (`BUILD_TYPE_UT=Debug`): doris_be_test compiles and links with
              zero duplicate symbols.
    - Deliberately breaking a unity skip entry fails the configure with the
    new fail-loud diagnostic; reverting restores a clean configure.
    
    - Behavior changed:
    - [x] Yes. Two latent wrong-code fixes surfaced by unity merges (details
    in
    the commit messages): `merger.cpp` and `column_predicate.h` threw with
    `INTERNAL_ERROR` accidentally bound to `PPlanFragmentCancelReason` (=3);
          they now carry `ErrorCode::INTERNAL_ERROR` as intended. Also
    `vdatetime_value.h`'s header-defined `static RE2` became a C++17 inline
    variable: one instance program-wide instead of one per including TU
          (same matching behavior, less startup work and memory).
    
    - Does this need documentation?
        - [x] No.
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    https://claude.ai/code/session_01Gdfkk7RqgD5e3Uv7bTM3NV
    
    ---------
    
    Co-authored-by: Claude Fable 5 <[email protected]>
---
 be/CMakeLists.txt                                  | 27 +++++++++++++-
 be/src/agent/CMakeLists.txt                        |  7 +++-
 be/src/agent/cgroup_cpu_ctl.h                      |  2 ++
 be/src/cloud/CMakeLists.txt                        | 12 +++++++
 be/src/cloud/cloud_internal_service.cpp            |  7 +---
 be/src/cloud/cloud_warm_up_manager.cpp             |  7 +---
 be/src/common/CMakeLists.txt                       | 16 +++++++++
 be/src/core/CMakeLists.txt                         | 38 ++++++++++++++++++++
 .../complex_type_deserialize_util.h                |  2 ++
 be/src/core/value/vdatetime_value.h                |  4 ++-
 be/src/exec/CMakeLists.txt                         |  2 +-
 be/src/exprs/CMakeLists.txt                        |  2 +-
 be/src/format/CMakeLists.txt                       | 15 ++++++++
 be/src/format_v2/column_mapper.cpp                 |  4 ---
 be/src/format_v2/column_mapper_nested.cpp          |  4 ---
 be/src/format_v2/expr/cast.h                       |  5 +++
 be/src/format_v2/parquet/parquet_scan.cpp          |  9 +----
 be/src/format_v2/parquet/parquet_statistics.cpp    |  9 +----
 be/src/format_v2/parquet/selection_vector.h        |  8 +++++
 be/src/format_v2/table/schema_history_util.cpp     |  7 ----
 be/src/format_v2/table/schema_history_util.h       |  8 +++++
 be/src/format_v2/table_reader.cpp                  |  8 +----
 be/src/gen_cpp/CMakeLists.txt                      | 18 +++++++++-
 be/src/io/CMakeLists.txt                           | 27 ++++++++++++++
 be/src/io/cache/block_file_cache.cpp               |  4 ---
 be/src/io/cache/file_cache_common.h                |  5 +++
 be/src/io/cache/lru_queue_recorder.cpp             |  8 +----
 be/src/load/CMakeLists.txt                         | 10 ++++++
 be/src/runtime/CMakeLists.txt                      | 14 ++++++++
 be/src/runtime/runtime_profile.h                   |  3 --
 be/src/service/CMakeLists.txt                      | 14 +++++---
 be/src/storage/CMakeLists.txt                      | 41 +++++++++++++++-------
 be/src/storage/index/ann/CMakeLists.txt            |  5 +++
 be/src/storage/merger.cpp                          | 20 +++++------
 be/src/storage/predicate/column_predicate.h        |  5 +--
 be/src/storage/segment/common.h                    |  5 +++
 be/src/storage/segment/external_col_meta_util.cpp  |  6 ++--
 be/src/storage/segment/segment.cpp                 |  2 +-
 be/src/storage/segment/segment_writer.cpp          |  4 +--
 be/src/storage/segment/segment_writer.h            |  3 --
 .../segment/variant/v2/variant_path_builder.cpp    |  4 ---
 .../segment/variant/v2/variant_shredder.cpp        |  5 +--
 be/src/storage/segment/vertical_segment_writer.cpp |  4 +--
 be/src/udf/CMakeLists.txt                          |  5 +++
 be/src/util/CMakeLists.txt                         | 19 ++++++++++
 be/src/util/bvar_windowed_adder.h                  |  6 ++++
 be/src/util/json/path_in_data.h                    |  6 ++++
 be/src/util/sm3.cpp                                |  6 ++--
 be/src/util/timezone_utils.cpp                     |  6 ++--
 .../fs_file_cache_storage_leak_cleaner_test.cpp    |  6 ++--
 50 files changed, 336 insertions(+), 128 deletions(-)

diff --git a/be/CMakeLists.txt b/be/CMakeLists.txt
index 0741d0a17dd..b2f1b8129ce 100644
--- a/be/CMakeLists.txt
+++ b/be/CMakeLists.txt
@@ -409,7 +409,14 @@ if (COMPILER_CLANG)
                         -Wthread-safety)
     add_compile_options(-Wno-gnu-statement-expression
                         -Wno-implicit-float-conversion
-                        -Wno-sign-conversion)
+                        -Wno-sign-conversion
+                        # libstdc++-15 puts `#pragma GCC unroll` on loops in 
its own
+                        # headers (bits/stl_algobase.h); when a 
sanitizer/coverage
+                        # build compiles at low optimization the unroller 
punts and
+                        # clang's -Wpass-failed turns that missed *hint* into 
an
+                        # -Werror failure. The diagnostic carries no 
correctness
+                        # signal, so drop it.
+                        -Wno-pass-failed)
     if (USE_LIBCPP)
         add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-stdlib=libc++>)
         add_definitions(-DUSE_LIBCPP)
@@ -981,6 +988,24 @@ function(pch_reuse target)
     endif()
 endfunction(pch_reuse target)
 
+# Every unity opt-out goes through this helper. set_source_files_properties()
+# silently ignores paths that do not exist, so a skip entry going stale after
+# a rename or move would quietly re-join its unity batch -- slower builds, or
+# new file-scope clashes, with no diagnostic anywhere. Fail the configure
+# instead. Entries under GENSRC_DIR are exempt: they are emitted by
+# add_custom_command at build time (wkt_lex.l.cpp, the generated
+# thrift/protobuf sources) and legitimately do not exist on a fresh configure.
+function(doris_skip_unity_inclusion)
+    foreach(entry IN LISTS ARGN)
+        string(FIND "${entry}" "${GENSRC_DIR}" gensrc_prefix_pos)
+        if(NOT gensrc_prefix_pos EQUAL 0 AND NOT EXISTS "${entry}")
+            message(FATAL_ERROR
+                "unity skip entry does not exist (renamed or moved?): 
${entry}")
+        endif()
+    endforeach()
+    set_source_files_properties(${ARGN} PROPERTIES SKIP_UNITY_BUILD_INCLUSION 
ON)
+endfunction()
+
 
 add_subdirectory(${SRC_DIR}/agent)
 add_subdirectory(${SRC_DIR}/common)
diff --git a/be/src/agent/CMakeLists.txt b/be/src/agent/CMakeLists.txt
index c680c41d6b2..423b9c5e1fb 100644
--- a/be/src/agent/CMakeLists.txt
+++ b/be/src/agent/CMakeLists.txt
@@ -29,4 +29,9 @@ endif()
 
 add_library(Agent STATIC ${AGENT_SOURCES})
 
-pch_reuse(Agent)
\ No newline at end of file
+pch_reuse(Agent)
+
+# Unity build: nine homogeneous task-worker glue TUs sharing the agent header
+# closure; batch 0 merges them into a single unity TU.
+set_target_properties(Agent PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                       UNITY_BUILD_BATCH_SIZE 0)
\ No newline at end of file
diff --git a/be/src/agent/cgroup_cpu_ctl.h b/be/src/agent/cgroup_cpu_ctl.h
index 262be57b499..3e1933fb4d6 100644
--- a/be/src/agent/cgroup_cpu_ctl.h
+++ b/be/src/agent/cgroup_cpu_ctl.h
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#pragma once
+
 #include <fcntl.h>
 #include <sys/stat.h>
 #include <sys/types.h>
diff --git a/be/src/cloud/CMakeLists.txt b/be/src/cloud/CMakeLists.txt
index dbe8160c2f8..e81a097b1ff 100644
--- a/be/src/cloud/CMakeLists.txt
+++ b/be/src/cloud/CMakeLists.txt
@@ -22,3 +22,15 @@ file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS *.cpp)
 add_library(Cloud STATIC ${SRC_FILES})
 
 pch_reuse(Cloud)
+
+# Unity build: homogeneous cloud glue TUs sharing the CloudStorageEngine /
+# meta-service RPC header closure. Batch 12 bounds jumbo-TU size and memory.
+# The two http action TUs stay individual: sibling TUs' file-scope
+# `using namespace ErrorCode` makes the unscoped HttpStatus enum constants
+# (OK, NOT_FOUND, ...) shadow ErrorCode variables under -Wshadow -Werror.
+set(CLOUD_UNITY_SKIP
+    ${CMAKE_CURRENT_SOURCE_DIR}/cloud_compaction_action.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/injection_point_action.cpp)
+doris_skip_unity_inclusion(${CLOUD_UNITY_SKIP})
+set_target_properties(Cloud PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                       UNITY_BUILD_BATCH_SIZE 12)
diff --git a/be/src/cloud/cloud_internal_service.cpp 
b/be/src/cloud/cloud_internal_service.cpp
index 0de9a78127a..d65e924fc4a 100644
--- a/be/src/cloud/cloud_internal_service.cpp
+++ b/be/src/cloud/cloud_internal_service.cpp
@@ -1002,12 +1002,7 @@ bvar::Adder<uint64_t> 
g_file_cache_warm_up_rowset_wait_for_compaction_num(
 bvar::Adder<uint64_t> 
g_file_cache_warm_up_rowset_wait_for_compaction_timeout_num(
         "file_cache_warm_up_rowset_wait_for_compaction_timeout_num");
 
-// Per-job windowed metrics for target BE
-// bvar::Window enforces MAX_SECONDS_LIMIT = 3600, so the longest window is 1h.
-static constexpr int WINDOW_5M = 300;
-static constexpr int WINDOW_30M = 1800;
-static constexpr int WINDOW_1H = 3600;
-
+// Per-job windowed metrics for target BE (window spans shared via 
bvar_windowed_adder.h)
 MBvarWindowedAdder 
g_warmup_ed_finish_segment_num("warmup_ed_finish_segment_num", {"job_id"},
                                                   {WINDOW_5M, WINDOW_30M, 
WINDOW_1H}, false);
 MBvarWindowedAdder 
g_warmup_ed_finish_segment_size("warmup_ed_finish_segment_size", {"job_id"},
diff --git a/be/src/cloud/cloud_warm_up_manager.cpp 
b/be/src/cloud/cloud_warm_up_manager.cpp
index 4590d96fb4c..68db44f0b1c 100644
--- a/be/src/cloud/cloud_warm_up_manager.cpp
+++ b/be/src/cloud/cloud_warm_up_manager.cpp
@@ -118,12 +118,7 @@ bvar::Adder<int64_t> 
g_file_cache_warm_up_job_num("file_cache_warm_up_job_num");
 bvar::LatencyRecorder g_file_cache_warm_up_rowset_wait_for_compaction_latency(
         "file_cache_warm_up_rowset_wait_for_compaction_latency");
 
-// Per-job windowed metrics for source BE
-// bvar::Window enforces MAX_SECONDS_LIMIT = 3600, so the longest window is 1h.
-static constexpr int WINDOW_5M = 300;
-static constexpr int WINDOW_30M = 1800;
-static constexpr int WINDOW_1H = 3600;
-
+// Per-job windowed metrics for source BE (window spans shared via 
bvar_windowed_adder.h)
 MBvarWindowedAdder 
g_warmup_ed_requested_segment_num("warmup_ed_requested_segment_num", {"job_id"},
                                                      {WINDOW_5M, WINDOW_30M, 
WINDOW_1H}, false);
 MBvarWindowedAdder 
g_warmup_ed_requested_segment_size("warmup_ed_requested_segment_size",
diff --git a/be/src/common/CMakeLists.txt b/be/src/common/CMakeLists.txt
index b1e51e8f303..949af9c9723 100644
--- a/be/src/common/CMakeLists.txt
+++ b/be/src/common/CMakeLists.txt
@@ -23,6 +23,22 @@ add_library(Common STATIC ${SRC_FILES})
 
 pch_reuse(Common)
 
+# Unity build for the small common TUs. Seven files leak file-scope macros
+# (SET_FIELD/UPDATE_FIELD, MEMORY_SANITIZER, DW_* tables, the DEFINE_*_METRIC
+# families, USE_PHDR_CACHE/UNW_LOCAL_ONLY) and stay individual -- that set
+# also keeps the three same-name metric-hook statics (_s_hook_name) apart.
+set(COMMON_UNITY_SKIP
+    ${CMAKE_CURRENT_SOURCE_DIR}/config.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/demangle.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/dwarf.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/metrics/doris_metrics.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/metrics/jvm_metrics.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/metrics/system_metrics.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/phdr_cache.cpp)
+doris_skip_unity_inclusion(${COMMON_UNITY_SKIP})
+set_target_properties(Common PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                        UNITY_BUILD_BATCH_SIZE 0)
+
 # Generate env_config.h according to env_config.h.in
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/env_config.h.in 
${GENSRC_DIR}/common/env_config.h)
 target_include_directories(Common PUBLIC ${GENSRC_DIR}/common/)
diff --git a/be/src/core/CMakeLists.txt b/be/src/core/CMakeLists.txt
index 348a375eef0..d5faec6c40c 100644
--- a/be/src/core/CMakeLists.txt
+++ b/be/src/core/CMakeLists.txt
@@ -32,3 +32,41 @@ pch_reuse(Core)
 # instantiations below without definitions. Opt this single TU out of the PCH.
 
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/wide_integer_from_double.cpp
                             PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
+
+# Unity build: column/data_type/serde glue TUs share the core header closure.
+# Opt-outs:
+# - column/column_vector.cpp: the heaviest template-instantiation TU in the
+#   target (~40s alone); it would dominate any batch it joins
+# - three macro-leak files (WRITE_INTEGRAL_COLUMN_TO_ORC,
+#   DECLARE_DECIMAL_COMPARISON, DELARE_DATE_ADD_INTERVAL)
+# - wide_integer_from_double.cpp: macro-leak, and it is the PCH-skipped
+#   explicit-instantiation TU above -- it must keep its own compile
+# - data_type_serde.cpp: holds member-level explicit instantiations of serde
+#   members whose class-level explicit instantiations live in the per-type
+#   serde TUs; merging both forms into one TU is a duplicate explicit
+#   instantiation
+# - the value/variant/ family (9s of slot time in total): copied file-local
+#   helpers with diverging signatures (require_bytes, write_unsigned, ...) --
+#   not worth renaming for the gain
+# - two files that tests compile a second time by #including the .cpp
+#   (column/column_variant.cpp, data_type/convert_field_to_type.cpp): the
+#   test object must shadow a never-pulled archive member, but a unity batch
+#   is pulled in for its siblings and the linker sees a duplicate definition
+set(CORE_UNITY_SKIP
+    ${CMAKE_CURRENT_SOURCE_DIR}/column/column_vector.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/column/column_variant.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/data_type/convert_field_to_type.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/data_type_serde/data_type_number_serde.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/data_type_serde/data_type_serde.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/field.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/value/vdatetime_value.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/value/variant/variant_batch_builder.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/value/variant/variant_canonical.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/value/variant/variant_field.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/value/variant/variant_metadata.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/value/variant/variant_scalar.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/value/variant/variant_value.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/wide_integer_from_double.cpp)
+doris_skip_unity_inclusion(${CORE_UNITY_SKIP})
+set_target_properties(Core PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                      UNITY_BUILD_BATCH_SIZE 12)
diff --git a/be/src/core/data_type_serde/complex_type_deserialize_util.h 
b/be/src/core/data_type_serde/complex_type_deserialize_util.h
index ff76d64dcd6..b1320b4b073 100644
--- a/be/src/core/data_type_serde/complex_type_deserialize_util.h
+++ b/be/src/core/data_type_serde/complex_type_deserialize_util.h
@@ -15,6 +15,8 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#pragma once
+
 #include "core/data_type_serde/data_type_serde.h"
 #include "core/string_ref.h"
 
diff --git a/be/src/core/value/vdatetime_value.h 
b/be/src/core/value/vdatetime_value.h
index 7419b021755..da0bba19bcb 100644
--- a/be/src/core/value/vdatetime_value.h
+++ b/be/src/core/value/vdatetime_value.h
@@ -219,7 +219,9 @@ static constexpr uint32_t DATEV2_YEAR_WIDTH = 23;
 static constexpr uint32_t DATETIMEV2_YEAR_WIDTH = 18;
 static constexpr uint32_t DATETIMEV2_MONTH_WIDTH = 4;
 
-static RE2 time_zone_offset_format_reg(R"(^[+-]{1}\d{2}\:\d{2}$)");
+// One shared instance program-wide (was `static`, i.e. one copy constructed
+// per including TU). Visiting is thread-safe.
+inline RE2 time_zone_offset_format_reg(R"(^[+-]{1}\d{2}\:\d{2}$)");
 
 uint8_t mysql_week_mode(uint32_t mode);
 
diff --git a/be/src/exec/CMakeLists.txt b/be/src/exec/CMakeLists.txt
index 7ec05378911..7ccbd60b5ea 100644
--- a/be/src/exec/CMakeLists.txt
+++ b/be/src/exec/CMakeLists.txt
@@ -52,7 +52,7 @@ set(EXEC_UNITY_SKIP
     
${CMAKE_CURRENT_SOURCE_DIR}/operator/partitioned_aggregation_sink_operator.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/operator/scan_operator.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/sink/writer/vfile_result_writer.cpp)
-set_source_files_properties(${EXEC_UNITY_SKIP} PROPERTIES 
SKIP_UNITY_BUILD_INCLUSION ON)
+doris_skip_unity_inclusion(${EXEC_UNITY_SKIP})
 set_target_properties(Exec PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
                                       UNITY_BUILD_BATCH_SIZE 12)
 
diff --git a/be/src/exprs/CMakeLists.txt b/be/src/exprs/CMakeLists.txt
index b7bf6916a90..1940ba6d8e4 100644
--- a/be/src/exprs/CMakeLists.txt
+++ b/be/src/exprs/CMakeLists.txt
@@ -97,7 +97,7 @@ set(EXPRS_UNITY_SKIP
     ${CMAKE_CURRENT_SOURCE_DIR}/math_functions.cpp
     ${GENSRC_DIR}/geo/wkt_lex.l.cpp
     ${GENSRC_DIR}/geo/wkt_yacc.y.cpp)
-set_source_files_properties(${EXPRS_UNITY_SKIP} PROPERTIES 
SKIP_UNITY_BUILD_INCLUSION ON)
+doris_skip_unity_inclusion(${EXPRS_UNITY_SKIP})
 set_target_properties(Exprs PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
                                        UNITY_BUILD_BATCH_SIZE 8)
 
diff --git a/be/src/format/CMakeLists.txt b/be/src/format/CMakeLists.txt
index f73ef2dbfaa..94b7c6bb6d1 100644
--- a/be/src/format/CMakeLists.txt
+++ b/be/src/format/CMakeLists.txt
@@ -29,3 +29,18 @@ list(APPEND SRC_FILES ${FORMAT_V2_SRC_FILES})
 add_library(Format STATIC ${SRC_FILES})
 
 pch_reuse(Format)
+
+# Unity build scoped to format_v2/: the v2 readers are the maintained line and
+# share one reader/expr header closure. The format/ (v1) tree is slated for
+# removal in a future version, so it is not worth the v1/v2 twin-symbol
+# deduplication a joint unity would require: every v1 file stays individual
+# until the tree is deleted. Within v2, adbc_reader.cpp stays individual
+# because its file-scope RETURN_IF_ADBC_ERROR macro must not leak into unity
+# siblings. Batch 8 bounds jumbo-TU size and memory.
+set(FORMAT_UNITY_SKIP ${SRC_FILES})
+list(FILTER FORMAT_UNITY_SKIP EXCLUDE REGEX ".*/format_v2/.*")
+list(APPEND FORMAT_UNITY_SKIP
+    ${CMAKE_CURRENT_SOURCE_DIR}/../format_v2/table/adbc_reader.cpp)
+doris_skip_unity_inclusion(${FORMAT_UNITY_SKIP})
+set_target_properties(Format PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                        UNITY_BUILD_BATCH_SIZE 8)
diff --git a/be/src/format_v2/column_mapper.cpp 
b/be/src/format_v2/column_mapper.cpp
index 9f433cc853f..e98a0cde9a1 100644
--- a/be/src/format_v2/column_mapper.cpp
+++ b/be/src/format_v2/column_mapper.cpp
@@ -349,10 +349,6 @@ static VExprSPtr create_file_slot_ref(const VSlotRef& 
slot_ref,
     return ref;
 }
 
-static bool is_cast_expr(const VExprSPtr& expr) {
-    return dynamic_cast<const Cast*>(expr.get()) != nullptr;
-}
-
 static bool is_binary_comparison_predicate(const VExprSPtr& expr) {
     if (expr == nullptr || expr->get_num_children() != 2 ||
         (expr->node_type() != TExprNodeType::BINARY_PRED &&
diff --git a/be/src/format_v2/column_mapper_nested.cpp 
b/be/src/format_v2/column_mapper_nested.cpp
index fefcdf26f12..9d1980c3579 100644
--- a/be/src/format_v2/column_mapper_nested.cpp
+++ b/be/src/format_v2/column_mapper_nested.cpp
@@ -37,10 +37,6 @@ namespace doris::format {
 
 namespace {
 
-static bool is_cast_expr(const VExprSPtr& expr) {
-    return dynamic_cast<const Cast*>(expr.get()) != nullptr;
-}
-
 static bool is_signed_integer_type(PrimitiveType type) {
     switch (type) {
     case TYPE_TINYINT:
diff --git a/be/src/format_v2/expr/cast.h b/be/src/format_v2/expr/cast.h
index 22604455e50..18b3bea676c 100644
--- a/be/src/format_v2/expr/cast.h
+++ b/be/src/format_v2/expr/cast.h
@@ -68,4 +68,9 @@ private:
     std::string _expr_name;
     FunctionBasePtr _function;
 };
+
+inline bool is_cast_expr(const VExprSPtr& expr) {
+    return dynamic_cast<const Cast*>(expr.get()) != nullptr;
+}
+
 } // namespace doris::format
diff --git a/be/src/format_v2/parquet/parquet_scan.cpp 
b/be/src/format_v2/parquet/parquet_scan.cpp
index a9154021999..115ea2e373d 100644
--- a/be/src/format_v2/parquet/parquet_scan.cpp
+++ b/be/src/format_v2/parquet/parquet_scan.cpp
@@ -49,6 +49,7 @@
 #include "format_v2/parquet/reader/native/column_chunk_reader.h"
 #include "format_v2/parquet/reader/native_column_reader.h"
 #include "format_v2/parquet/reader/row_position_column_reader.h"
+#include "format_v2/parquet/selection_vector.h" // count_range_rows
 #include "runtime/runtime_state.h"
 #include "util/defer_op.h"
 #include "util/time.h"
@@ -823,14 +824,6 @@ Status execute_batch_filters(const 
format::FileScanRequest& request, int64_t bat
 }
 
 namespace {
-int64_t count_range_rows(const std::vector<RowRange>& ranges) {
-    int64_t rows = 0;
-    for (const auto& range : ranges) {
-        rows += range.length;
-    }
-    return rows;
-}
-
 void append_intersection(const RowRange& left, const RowRange& right,
                          std::vector<RowRange>& result) {
     const int64_t start = std::max(left.start, right.start);
diff --git a/be/src/format_v2/parquet/parquet_statistics.cpp 
b/be/src/format_v2/parquet/parquet_statistics.cpp
index e6f42c59ce6..b67536fd02c 100644
--- a/be/src/format_v2/parquet/parquet_statistics.cpp
+++ b/be/src/format_v2/parquet/parquet_statistics.cpp
@@ -42,6 +42,7 @@
 #include "format_v2/parquet/parquet_file_context.h"
 #include "format_v2/parquet/reader/native/block_split_bloom_filter.h"
 #include "format_v2/parquet/reader/native_column_reader.h"
+#include "format_v2/parquet/selection_vector.h" // count_range_rows
 #include "format_v2/timestamp_statistics.h"
 #include "runtime/runtime_profile.h"
 #include "storage/index/bloom_filter/bloom_filter.h"
@@ -989,14 +990,6 @@ std::vector<RowRange> intersect_ranges(const 
std::vector<RowRange>& left,
     return result;
 }
 
-int64_t count_range_rows(const std::vector<RowRange>& ranges) {
-    int64_t rows = 0;
-    for (const auto& range : ranges) {
-        rows += range.length;
-    }
-    return rows;
-}
-
 void append_row_range(const RowRange& range, std::vector<RowRange>* ranges) {
     if (range.length == 0) {
         return;
diff --git a/be/src/format_v2/parquet/selection_vector.h 
b/be/src/format_v2/parquet/selection_vector.h
index 99c854d8b4e..a9c8c040e93 100644
--- a/be/src/format_v2/parquet/selection_vector.h
+++ b/be/src/format_v2/parquet/selection_vector.h
@@ -31,6 +31,14 @@ struct RowRange {
     int64_t length = 0;
 };
 
+inline int64_t count_range_rows(const std::vector<RowRange>& ranges) {
+    int64_t rows = 0;
+    for (const auto& range : ranges) {
+        rows += range.length;
+    }
+    return rows;
+}
+
 struct ParquetPageSkipPlan {
     int leaf_column_id = -1;
     // Page ordinal is the data-page ordinal in the column chunk. It 
intentionally excludes
diff --git a/be/src/format_v2/table/schema_history_util.cpp 
b/be/src/format_v2/table/schema_history_util.cpp
index 96a466fa772..a3dbad7c1e3 100644
--- a/be/src/format_v2/table/schema_history_util.cpp
+++ b/be/src/format_v2/table/schema_history_util.cpp
@@ -27,13 +27,6 @@
 namespace doris::format {
 namespace {
 
-const schema::external::TField* get_field_ptr(const 
schema::external::TFieldPtr& field_ptr) {
-    if (!field_ptr.__isset.field_ptr || field_ptr.field_ptr == nullptr) {
-        return nullptr;
-    }
-    return field_ptr.field_ptr.get();
-}
-
 const schema::external::TField* find_child_field_by_name(
         const std::vector<schema::external::TFieldPtr>& fields, const 
std::string& name) {
     for (const auto& field_ptr : fields) {
diff --git a/be/src/format_v2/table/schema_history_util.h 
b/be/src/format_v2/table/schema_history_util.h
index 3c4a80b5d4c..49704c5fb98 100644
--- a/be/src/format_v2/table/schema_history_util.h
+++ b/be/src/format_v2/table/schema_history_util.h
@@ -27,6 +27,14 @@
 
 namespace doris::format {
 
+// Unwrap a thrift TFieldPtr, returning nullptr when the pointer is unset.
+inline const schema::external::TField* get_field_ptr(const 
schema::external::TFieldPtr& field_ptr) {
+    if (!field_ptr.__isset.field_ptr || field_ptr.field_ptr == nullptr) {
+        return nullptr;
+    }
+    return field_ptr.field_ptr.get();
+}
+
 const schema::external::TSchema* find_history_schema(const 
TFileScanRangeParams* params,
                                                      int64_t schema_id);
 
diff --git a/be/src/format_v2/table_reader.cpp 
b/be/src/format_v2/table_reader.cpp
index 40ffe6cb86e..b531ff9cf23 100644
--- a/be/src/format_v2/table_reader.cpp
+++ b/be/src/format_v2/table_reader.cpp
@@ -50,6 +50,7 @@
 #include "format_v2/native/native_reader.h"
 #include "format_v2/orc/orc_reader.h"
 #include "format_v2/parquet/parquet_reader.h"
+#include "format_v2/table/schema_history_util.h" // get_field_ptr
 #include "runtime/file_scan_profile.h"
 #include "storage/segment/condition_cache.h"
 #include "util/debug_points.h"
@@ -140,13 +141,6 @@ std::string partition_values_debug_string(const 
std::map<std::string, Field>& pa
     return out.str();
 }
 
-const schema::external::TField* get_field_ptr(const 
schema::external::TFieldPtr& field_ptr) {
-    if (!field_ptr.__isset.field_ptr || field_ptr.field_ptr == nullptr) {
-        return nullptr;
-    }
-    return field_ptr.field_ptr.get();
-}
-
 const schema::external::TField* find_external_field_by_id(
         const schema::external::TStructField* root, int32_t field_id) {
     if (root == nullptr || !root->__isset.fields) {
diff --git a/be/src/gen_cpp/CMakeLists.txt b/be/src/gen_cpp/CMakeLists.txt
index c4463f75520..abbe3877079 100644
--- a/be/src/gen_cpp/CMakeLists.txt
+++ b/be/src/gen_cpp/CMakeLists.txt
@@ -27,10 +27,26 @@ list(FILTER SRC_FILES EXCLUDE REGEX 
"_server\\.skeleton\\.cpp$")
 
 add_compile_options(-Wno-return-type)
 
-# keep everything in one library, the object files reference 
+# keep everything in one library, the object files reference
 # each other
 add_library(DorisGen STATIC ${SRC_FILES})
 
+# Unity build for the thrift-generated .cpp half (pre-scanned clean: no
+# file-scope macros or duplicate statics). Generated sources cannot be edited,
+# so anything that clashes can only be opted out, never fixed:
+# - every protobuf .cc stays individual: protoc emits the same file-scope
+#   statics (schemas[], file_default_instances[]) in each one, a structural
+#   clash for any merged pair
+# - the two heaviest thrift TUs stay individual so no batch inherits them
+set(GEN_UNITY_SKIP ${SRC_FILES})
+list(FILTER GEN_UNITY_SKIP INCLUDE REGEX "\\.cc$")
+list(APPEND GEN_UNITY_SKIP
+    ${GEN_CPP_DIR}/FrontendService_types.cpp
+    ${GEN_CPP_DIR}/PlanNodes_types.cpp)
+doris_skip_unity_inclusion(${GEN_UNITY_SKIP})
+set_target_properties(DorisGen PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                          UNITY_BUILD_BATCH_SIZE 8)
+
 if (COMPILER_CLANG)
     target_compile_options(DorisGen PRIVATE
     -Wno-implicit-int-conversion
diff --git a/be/src/io/CMakeLists.txt b/be/src/io/CMakeLists.txt
index 56c2eeb94a3..3026c82e11f 100644
--- a/be/src/io/CMakeLists.txt
+++ b/be/src/io/CMakeLists.txt
@@ -34,11 +34,38 @@ if(ENABLE_TDE)
 endif()
 
 list(REMOVE_ITEM IO_FILES 
"${CMAKE_CURRENT_SOURCE_DIR}/fs/benchmark/fs_benchmark_tool.cpp")
+# Standalone tool with its own main(); must not be an archive member of 
libIO.a,
+# or unity builds merge it into an object that the doris_be link actually 
pulls in.
+list(REMOVE_ITEM IO_FILES 
"${CMAKE_CURRENT_SOURCE_DIR}/cache/file_cache_lru_tool.cpp")
 
 add_library(IO STATIC ${IO_FILES})
 
 pch_reuse(IO)
 
+# Unity build for the io glue (small fs/cache TUs, parse-cost dominated).
+# Opt-outs:
+# - three filesystem TUs whose CHECK_*_CLIENT file-scope macros must not
+#   leak into unity siblings
+# - http_file_system.cpp: sibling TUs' file-scope `using namespace ErrorCode`
+#   makes the unscoped HttpStatus enum constants shadow ErrorCode variables
+#   under -Wshadow -Werror (same pattern as the cloud http actions)
+# - benchmark sources and ENABLE_TDE module swaps stay individual
+set(IO_UNITY_SKIP
+    ${CMAKE_CURRENT_SOURCE_DIR}/fs/broker_file_system.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/fs/hdfs_file_system.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/fs/s3_file_system.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/fs/http_file_system.cpp)
+file(GLOB_RECURSE IO_UNITY_BENCH_SRCS CONFIGURE_DEPENDS
+    ${CMAKE_CURRENT_SOURCE_DIR}/fs/benchmark/*.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/tools/*.cpp)
+list(APPEND IO_UNITY_SKIP ${IO_UNITY_BENCH_SRCS})
+if (ENABLE_TDE)
+    list(APPEND IO_UNITY_SKIP ${EXTRA_SOURCES})
+endif()
+doris_skip_unity_inclusion(${IO_UNITY_SKIP})
+set_target_properties(IO PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                    UNITY_BUILD_BATCH_SIZE 16)
+
 if (${BUILD_FS_BENCHMARK} STREQUAL "ON")
     add_executable(fs_benchmark_tool
         fs/benchmark/fs_benchmark_tool.cpp
diff --git a/be/src/io/cache/block_file_cache.cpp 
b/be/src/io/cache/block_file_cache.cpp
index b44679a94fa..c4e7ef47853 100644
--- a/be/src/io/cache/block_file_cache.cpp
+++ b/be/src/io/cache/block_file_cache.cpp
@@ -66,10 +66,6 @@ namespace {
 constexpr std::array<FileCacheType, 4> LRU_LOG_REPLAY_TYPES = {
         FileCacheType::TTL, FileCacheType::INDEX, FileCacheType::NORMAL, 
FileCacheType::DISPOSABLE};
 
-size_t file_cache_type_index(FileCacheType type) {
-    return static_cast<size_t>(type);
-}
-
 } // namespace
 
 // Insert a block pointer into one shard while swallowing allocation failures.
diff --git a/be/src/io/cache/file_cache_common.h 
b/be/src/io/cache/file_cache_common.h
index 8b52af8d161..3f8ca5e1ff0 100644
--- a/be/src/io/cache/file_cache_common.h
+++ b/be/src/io/cache/file_cache_common.h
@@ -43,6 +43,11 @@ enum FileCacheType {
     DISPOSABLE = 0,
     TTL = 3,
 };
+
+inline size_t file_cache_type_index(FileCacheType type) {
+    return static_cast<size_t>(type);
+}
+
 std::string cache_type_to_surfix(FileCacheType type);
 FileCacheType surfix_to_cache_type(const std::string& str);
 
diff --git a/be/src/io/cache/lru_queue_recorder.cpp 
b/be/src/io/cache/lru_queue_recorder.cpp
index 314a444e232..82edc5f6070 100644
--- a/be/src/io/cache/lru_queue_recorder.cpp
+++ b/be/src/io/cache/lru_queue_recorder.cpp
@@ -24,13 +24,7 @@
 
 namespace doris::io {
 
-namespace {
-
-size_t file_cache_type_index(FileCacheType type) {
-    return static_cast<size_t>(type);
-}
-
-} // namespace
+namespace {} // namespace
 
 void LRUQueueRecorder::record_queue_event(FileCacheType type, CacheLRULogType 
log_type,
                                           const UInt128Wrapper hash, const 
size_t offset,
diff --git a/be/src/load/CMakeLists.txt b/be/src/load/CMakeLists.txt
index 5c2e970f6d9..5faf360734f 100644
--- a/be/src/load/CMakeLists.txt
+++ b/be/src/load/CMakeLists.txt
@@ -25,3 +25,13 @@ file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS *.cpp)
 add_library(Load STATIC ${SRC_FILES})
 
 pch_reuse(Load)
+
+# Unity build: load channel/delta-writer/group-commit glue sharing one header
+# closure. Two files leak file-scope macros (UNKNOWN_ID_FOR_TEST,
+# HANDLE_ERROR/HANDLE_MULTI_TABLE_ERROR) and stay individual.
+set(LOAD_UNITY_SKIP
+    ${CMAKE_CURRENT_SOURCE_DIR}/channel/load_stream.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/routine_load/routine_load_task_executor.cpp)
+doris_skip_unity_inclusion(${LOAD_UNITY_SKIP})
+set_target_properties(Load PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                      UNITY_BUILD_BATCH_SIZE 12)
diff --git a/be/src/runtime/CMakeLists.txt b/be/src/runtime/CMakeLists.txt
index 7d54f9bd76b..0d2f3b567d2 100644
--- a/be/src/runtime/CMakeLists.txt
+++ b/be/src/runtime/CMakeLists.txt
@@ -34,3 +34,17 @@ add_library(Runtime STATIC
 )
 
 pch_reuse(Runtime)
+
+# Unity build: runtime glue TUs share the exec-env/runtime-state header
+# closure. memory/jemalloc_hook.cpp (a Linux-only member, absent on macOS)
+# stays individual: it defines malloc-replacement hooks and leaks
+# __THROW/ALIAS macros. descriptors.cpp stays individual: its test compiles
+# it a second time by #including the .cpp, and the test object must shadow a
+# never-pulled archive member (a unity batch would get pulled in for its
+# siblings and hand the linker a duplicate definition).
+set(RUNTIME_UNITY_SKIP
+    ${CMAKE_CURRENT_SOURCE_DIR}/memory/jemalloc_hook.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/descriptors.cpp)
+doris_skip_unity_inclusion(${RUNTIME_UNITY_SKIP})
+set_target_properties(Runtime PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                         UNITY_BUILD_BATCH_SIZE 12)
diff --git a/be/src/runtime/runtime_profile.h b/be/src/runtime/runtime_profile.h
index 54f2e80c89e..662a92db11d 100644
--- a/be/src/runtime/runtime_profile.h
+++ b/be/src/runtime/runtime_profile.h
@@ -746,9 +746,6 @@ private:
     int64_t _metadata;
     bool _is_set_metadata = false;
 
-    bool _is_sink = false;
-    bool _is_set_sink = false;
-
     // The timestamp when the profile was modified, make sure the update is up 
to date.
     time_t _timestamp;
 
diff --git a/be/src/service/CMakeLists.txt b/be/src/service/CMakeLists.txt
index 28985a2e031..f07b896d4a4 100644
--- a/be/src/service/CMakeLists.txt
+++ b/be/src/service/CMakeLists.txt
@@ -37,16 +37,20 @@ add_library(Service STATIC ${SRC_FILES})
 pch_reuse(Service)
 
 # Unity build scoped to the http glue: ~60 small handlers re-parsing the same
-# header closure once per file. Non-http sources (service entry points,
-# arrow_flight) are heterogeneous heavy TUs that gain nothing from merging.
-# http_parser.cpp and be_thread_stack_action.cpp stay individual because their
-# file-scope macros (CR/LF, UNW_LOCAL_ONLY) must not leak into unity siblings.
+# header closure once per file, merged into one unity TU (batch 0). Widening
+# to the whole target at batch 8 was tried and measured slower: splitting the
+# single http jumbo into 8-file batches repays the shared-closure parse per
+# batch, and the heterogeneous non-http TUs gain too little to cover it
+# (service segment 104s -> 132s slot time). So non-http sources stay
+# individual. http_parser.cpp and be_thread_stack_action.cpp stay individual
+# because their file-scope macros (CR/LF, UNW_LOCAL_ONLY) must not leak into
+# unity siblings.
 set(SERVICE_UNITY_SKIP ${SRC_FILES})
 list(FILTER SERVICE_UNITY_SKIP EXCLUDE REGEX ".*/service/http/.*")
 list(APPEND SERVICE_UNITY_SKIP
     ${CMAKE_CURRENT_SOURCE_DIR}/http/http_parser.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/http/action/be_thread_stack_action.cpp)
-set_source_files_properties(${SERVICE_UNITY_SKIP} PROPERTIES 
SKIP_UNITY_BUILD_INCLUSION ON)
+doris_skip_unity_inclusion(${SERVICE_UNITY_SKIP})
 set_target_properties(Service PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
                                          UNITY_BUILD_BATCH_SIZE 0)
 
diff --git a/be/src/storage/CMakeLists.txt b/be/src/storage/CMakeLists.txt
index 888b16ebe32..21e82183f58 100644
--- a/be/src/storage/CMakeLists.txt
+++ b/be/src/storage/CMakeLists.txt
@@ -46,19 +46,36 @@ endif()
 
 pch_reuse(Storage)
 
-# Unity build scoped to storage/index/: 115 homogeneous reader/writer/iterator
-# TUs sharing one (CLucene-heavy) header closure. The rest of Storage keeps
-# compiling individually. Batch 32 bounds jumbo-TU size and memory. Four index
-# files stay individual because their file-scope macros (CL_MAX_PATH and
-# friends, IS_CHINESE_CHAR, APPLY_FOR_PRIMITITYPE) must not leak into unity
-# siblings.
-set(STORAGE_UNITY_SKIP ${SRC_FILES})
-list(FILTER STORAGE_UNITY_SKIP EXCLUDE REGEX ".*/storage/index/.*")
-list(APPEND STORAGE_UNITY_SKIP
+# Unity build for the whole Storage target: segment/rowset/tablet/compaction/
+# index glue TUs re-parse the same storage header closure once per file, so
+# batching them cuts the repeated frontend work. Batch 12 bounds jumbo-TU size
+# and memory. Opted out:
+# - seven files whose file-scope macros (CL_MAX_PATH and friends,
+#   IS_CHINESE_CHAR, APPLY_FOR_PRIMITITYPE, RETURN_IF_NOT_EOF_AND_OK,
+#   FORMAT_*_ADD_JSON_NODE, RETURN_IF_ERROR_) must not leak into unity siblings
+# - the three heaviest template-instantiation TUs (predicate creators) which
+#   would dominate any batch they join
+# - compaction/collection_statistics.cpp: its test compiles it a second time
+#   by #including the .cpp; the test object must shadow a never-pulled archive
+#   member, but a unity batch is pulled in for its siblings and the linker
+#   sees a duplicate definition
+set(STORAGE_UNITY_SKIP
     
${CMAKE_CURRENT_SOURCE_DIR}/index/inverted/inverted_index_compound_reader.cpp
     ${CMAKE_CURRENT_SOURCE_DIR}/index/inverted/inverted_index_fs_directory.cpp
     
${CMAKE_CURRENT_SOURCE_DIR}/index/inverted/tokenizer/basic/basic_tokenizer.cpp
-    ${CMAKE_CURRENT_SOURCE_DIR}/index/zone_map/zone_map_index.cpp)
-set_source_files_properties(${STORAGE_UNITY_SKIP} PROPERTIES 
SKIP_UNITY_BUILD_INCLUSION ON)
+    ${CMAKE_CURRENT_SOURCE_DIR}/index/zone_map/zone_map_index.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/iterator/vcollect_iterator.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/tablet/tablet.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/task/engine_clone_task.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/predicate/predicate_creator_comparison.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/predicate/predicate_creator_in_list_in.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/predicate/predicate_creator_in_list_not_in.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/compaction/collection_statistics.cpp)
+if (ENABLE_VARIANT_NESTED_GROUP)
+    # Out-of-tree module sources swapped into this target: unity hygiene
+    # unaudited, keep them individual.
+    list(APPEND STORAGE_UNITY_SKIP ${VARIANT_NESTED_GROUP_SOURCES})
+endif()
+doris_skip_unity_inclusion(${STORAGE_UNITY_SKIP})
 set_target_properties(Storage PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
-                                         UNITY_BUILD_BATCH_SIZE 32)
+                                         UNITY_BUILD_BATCH_SIZE 12)
diff --git a/be/src/storage/index/ann/CMakeLists.txt 
b/be/src/storage/index/ann/CMakeLists.txt
index a30bfce9773..d671cdbf024 100644
--- a/be/src/storage/index/ann/CMakeLists.txt
+++ b/be/src/storage/index/ann/CMakeLists.txt
@@ -30,3 +30,8 @@ target_link_libraries(ann_index PUBLIC faiss 
OpenMP::OpenMP_CXX)
 
 # Some header files from faiss are used by doris, they will break compile 
check.
 target_compile_options(ann_index PRIVATE -Wno-shadow-field)
+
+# Unity build: ten homogeneous TUs sharing the faiss header closure; batch 0
+# merges them into a single unity TU.
+set_target_properties(ann_index PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                           UNITY_BUILD_BATCH_SIZE 0)
diff --git a/be/src/storage/merger.cpp b/be/src/storage/merger.cpp
index d986b367288..c8abc92e7f7 100644
--- a/be/src/storage/merger.cpp
+++ b/be/src/storage/merger.cpp
@@ -121,8 +121,8 @@ Status Merger::vmerge_rowsets(BaseTabletSPtr tablet, 
ReaderType reader_type,
         auto tablet_state = tablet->tablet_state();
         if (tablet_state != TABLET_RUNNING && tablet_state != TABLET_NOTREADY) 
{
             tablet->clear_cache();
-            return Status::Error<INTERNAL_ERROR>("tablet {} is not used any 
more",
-                                                 tablet->tablet_id());
+            return Status::Error<ErrorCode::INTERNAL_ERROR>("tablet {} is not 
used any more",
+                                                            
tablet->tablet_id());
         }
 
         // Read one block from block reader
@@ -144,8 +144,8 @@ Status Merger::vmerge_rowsets(BaseTabletSPtr tablet, 
ReaderType reader_type,
         block.clear_column_data();
     }
     if (ExecEnv::GetInstance()->storage_engine().stopped()) {
-        return Status::Error<INTERNAL_ERROR>("tablet {} failed to do 
compaction, engine stopped",
-                                             tablet->tablet_id());
+        return Status::Error<ErrorCode::INTERNAL_ERROR>(
+                "tablet {} failed to do compaction, engine stopped", 
tablet->tablet_id());
     }
 
     if (stats_output != nullptr) {
@@ -312,8 +312,8 @@ Status Merger::vertical_compact_one_group(
         auto tablet_state = tablet->tablet_state();
         if (tablet_state != TABLET_RUNNING && tablet_state != TABLET_NOTREADY) 
{
             tablet->clear_cache();
-            return Status::Error<INTERNAL_ERROR>("tablet {} is not used any 
more",
-                                                 tablet->tablet_id());
+            return Status::Error<ErrorCode::INTERNAL_ERROR>("tablet {} is not 
used any more",
+                                                            
tablet->tablet_id());
         }
         // Read one block from block reader
         
RETURN_NOT_OK_STATUS_WITH_WARN(reader.next_block_with_aggregation(&block, &eof),
@@ -335,8 +335,8 @@ Status Merger::vertical_compact_one_group(
         block.clear_column_data();
     }
     if (ExecEnv::GetInstance()->storage_engine().stopped()) {
-        return Status::Error<INTERNAL_ERROR>("tablet {} failed to do 
compaction, engine stopped",
-                                             tablet->tablet_id());
+        return Status::Error<ErrorCode::INTERNAL_ERROR>(
+                "tablet {} failed to do compaction, engine stopped", 
tablet->tablet_id());
     }
 
     if (stats_output != nullptr) {
@@ -391,8 +391,8 @@ Status Merger::vertical_compact_one_group(
         block.clear_column_data();
     }
     if (ExecEnv::GetInstance()->storage_engine().stopped()) {
-        return Status::Error<INTERNAL_ERROR>("tablet {} failed to do 
compaction, engine stopped",
-                                             tablet_id);
+        return Status::Error<ErrorCode::INTERNAL_ERROR>(
+                "tablet {} failed to do compaction, engine stopped", 
tablet_id);
     }
 
     if (stats_output != nullptr) {
diff --git a/be/src/storage/predicate/column_predicate.h 
b/be/src/storage/predicate/column_predicate.h
index 2bcc8359464..1d55531eb5e 100644
--- a/be/src/storage/predicate/column_predicate.h
+++ b/be/src/storage/predicate/column_predicate.h
@@ -349,7 +349,8 @@ public:
         if (_predicate_input_rows_counter == nullptr ||
             _predicate_filtered_rows_counter == nullptr ||
             _predicate_always_true_rows_counter == nullptr) {
-            throw Exception(INTERNAL_ERROR, "Predicate profile counters are 
not initialized");
+            throw Exception(ErrorCode::INTERNAL_ERROR,
+                            "Predicate profile counters are not initialized");
         }
         COUNTER_UPDATE(_predicate_input_rows_counter, input_rows);
         COUNTER_UPDATE(_predicate_filtered_rows_counter, filter_rows);
@@ -397,7 +398,7 @@ public:
 protected:
     virtual bool _can_ignore() const { return _runtime_filter_id != -1; }
     virtual uint16_t _evaluate_inner(const IColumn& column, uint16_t* sel, 
uint16_t size) const {
-        throw Exception(INTERNAL_ERROR, "Not Implemented _evaluate_inner");
+        throw Exception(ErrorCode::INTERNAL_ERROR, "Not Implemented 
_evaluate_inner");
     }
 
     void reset_judge_selectivity() const { 
_rf_selectivity.reset_judge_selectivity(); }
diff --git a/be/src/storage/segment/common.h b/be/src/storage/segment/common.h
index 166aa9fca58..a35fef0a97e 100644
--- a/be/src/storage/segment/common.h
+++ b/be/src/storage/segment/common.h
@@ -30,5 +30,10 @@ namespace segment_v2 {
 using rowid_t = uint32_t;
 using ordinal_t = uint64_t;
 
+// Magic footer bytes identifying a V2 segment file, written by the segment
+// writers and checked when parsing the footer.
+inline constexpr const char* k_segment_magic = "D0R1";
+inline constexpr uint32_t k_segment_magic_length = 4;
+
 } // namespace segment_v2
 } // namespace doris
diff --git a/be/src/storage/segment/external_col_meta_util.cpp 
b/be/src/storage/segment/external_col_meta_util.cpp
index 87bc31f1079..9bc4bfeba13 100644
--- a/be/src/storage/segment/external_col_meta_util.cpp
+++ b/be/src/storage/segment/external_col_meta_util.cpp
@@ -29,8 +29,8 @@ namespace doris::segment_v2 {
 
 namespace {
 
-io::IOContext create_index_io_context(const io::IOContext* source_io_ctx,
-                                      OlapReaderStatistics* stats) {
+io::IOContext create_ext_meta_io_context(const io::IOContext* source_io_ctx,
+                                         OlapReaderStatistics* stats) {
     io::IOContext io_ctx;
     if (source_io_ctx != nullptr) {
         io_ctx = *source_io_ctx;
@@ -145,7 +145,7 @@ Status ExternalColMetaUtil::read_col_meta(const 
io::FileReaderSPtr& file_reader,
     std::string buf;
     buf.resize(static_cast<size_t>(size));
     size_t meta_read = 0;
-    io::IOContext io_ctx = create_index_io_context(source_io_ctx, stats);
+    io::IOContext io_ctx = create_ext_meta_io_context(source_io_ctx, stats);
     RETURN_IF_ERROR(file_reader->read_at(pos, Slice(buf.data(), buf.size()), 
&meta_read, &io_ctx));
     if (meta_read != size) {
         return Status::Corruption("short read ColumnMetaPB: expect={}, 
actual={}", size, meta_read);
diff --git a/be/src/storage/segment/segment.cpp 
b/be/src/storage/segment/segment.cpp
index 9e58a76e0a1..be80f7ae530 100644
--- a/be/src/storage/segment/segment.cpp
+++ b/be/src/storage/segment/segment.cpp
@@ -73,11 +73,11 @@
 #include "storage/segment/column_meta_accessor.h"
 #include "storage/segment/column_reader.h"
 #include "storage/segment/column_reader_cache.h"
+#include "storage/segment/common.h" // k_segment_magic
 #include "storage/segment/empty_segment_iterator.h"
 #include "storage/segment/page_io.h"
 #include "storage/segment/page_pointer.h"
 #include "storage/segment/segment_iterator.h"
-#include "storage/segment/segment_writer.h" // k_segment_magic_length
 #include "storage/segment/stream_reader.h"
 #include "storage/segment/variant/variant_column_reader.h"
 #include "storage/tablet/tablet_schema.h"
diff --git a/be/src/storage/segment/segment_writer.cpp 
b/be/src/storage/segment/segment_writer.cpp
index ed2b403c75f..2bdefe39ef7 100644
--- a/be/src/storage/segment/segment_writer.cpp
+++ b/be/src/storage/segment/segment_writer.cpp
@@ -62,6 +62,7 @@
 #include "storage/rowset/rowset_writer_context.h" // RowsetWriterContext
 #include "storage/rowset/segment_creator.h"
 #include "storage/segment/column_writer.h" // ColumnWriter
+#include "storage/segment/common.h"        // k_segment_magic
 #include "storage/segment/encoding_info.h"
 #include "storage/segment/external_col_meta_util.h"
 #include "storage/segment/page_io.h"
@@ -80,9 +81,6 @@ namespace segment_v2 {
 
 using namespace ErrorCode;
 
-const char* k_segment_magic = "D0R1";
-const uint32_t k_segment_magic_length = 4;
-
 inline std::string segment_mem_tracker_name(uint32_t segment_id) {
     return "SegmentWriter:Segment-" + std::to_string(segment_id);
 }
diff --git a/be/src/storage/segment/segment_writer.h 
b/be/src/storage/segment/segment_writer.h
index be22adcefaa..ba5d2f9af44 100644
--- a/be/src/storage/segment/segment_writer.h
+++ b/be/src/storage/segment/segment_writer.h
@@ -60,9 +60,6 @@ class FileWriter;
 
 namespace segment_v2 {
 
-extern const char* k_segment_magic;
-extern const uint32_t k_segment_magic_length;
-
 class VariantStatsCaculator;
 
 struct SegmentWriterOptions {
diff --git a/be/src/storage/segment/variant/v2/variant_path_builder.cpp 
b/be/src/storage/segment/variant/v2/variant_path_builder.cpp
index c7542669fe4..d908963ef74 100644
--- a/be/src/storage/segment/variant/v2/variant_path_builder.cpp
+++ b/be/src/storage/segment/variant/v2/variant_path_builder.cpp
@@ -849,10 +849,6 @@ size_t dotted_path_depth(const PathInData& path) {
     return path.get_parts().size();
 }
 
-size_t path_allocated_bytes(const PathInData& path) {
-    return path.get_path().capacity() + path.get_parts().capacity() * 
sizeof(PathInData::Part);
-}
-
 size_t recursive_null_count(const IColumn& column) {
     if (const auto* nullable = check_and_get_column<ColumnNullable>(column)) {
         size_t count = 0;
diff --git a/be/src/storage/segment/variant/v2/variant_shredder.cpp 
b/be/src/storage/segment/variant/v2/variant_shredder.cpp
index d61b51aed96..99c312a8326 100644
--- a/be/src/storage/segment/variant/v2/variant_shredder.cpp
+++ b/be/src/storage/segment/variant/v2/variant_shredder.cpp
@@ -35,6 +35,7 @@
 #include "exec/common/variant_util.h"
 #include "exprs/function/parse/variant_jsonb_parse.h"
 #include "storage/tablet/tablet_schema.h"
+#include "util/json/path_in_data.h"
 #include "util/jsonb_writer.h"
 
 namespace doris::segment_v2 {
@@ -52,10 +53,6 @@ PathInData normalize_doc_publication_path(const PathInData& 
path) {
     return PathInData(path.get_path(), path.get_is_typed());
 }
 
-size_t path_allocated_bytes(const PathInData& path) {
-    return path.get_path().capacity() + path.get_parts().capacity() * 
sizeof(PathInData::Part);
-}
-
 } // namespace
 
 struct VariantShredder::Impl {
diff --git a/be/src/storage/segment/vertical_segment_writer.cpp 
b/be/src/storage/segment/vertical_segment_writer.cpp
index abbdb857bc4..319597a0418 100644
--- a/be/src/storage/segment/vertical_segment_writer.cpp
+++ b/be/src/storage/segment/vertical_segment_writer.cpp
@@ -68,6 +68,7 @@
 #include "storage/rowset/rowset_writer_context.h" // RowsetWriterContext
 #include "storage/rowset/segment_creator.h"
 #include "storage/segment/column_writer.h" // ColumnWriter
+#include "storage/segment/common.h"        // k_segment_magic
 #include "storage/segment/encoding_info.h"
 #include "storage/segment/external_col_meta_util.h"
 #include "storage/segment/historical_row_retriever.h"
@@ -88,9 +89,6 @@ namespace doris::segment_v2 {
 
 using namespace ErrorCode;
 
-static constexpr const char* k_segment_magic = "D0R1";
-static constexpr uint32_t k_segment_magic_length = 4;
-
 inline std::string vertical_segment_writer_mem_tracker_name(uint32_t 
segment_id) {
     return "VerticalSegmentWriter:Segment-" + std::to_string(segment_id);
 }
diff --git a/be/src/udf/CMakeLists.txt b/be/src/udf/CMakeLists.txt
index 0d57e85f5b1..45e28f93cb4 100755
--- a/be/src/udf/CMakeLists.txt
+++ b/be/src/udf/CMakeLists.txt
@@ -26,3 +26,8 @@ file(GLOB PYTHON_UDF_SOURCES "python/*.cpp")
 # can have dependencies on our other libs. The second version is shipped as 
part
 # of the UDF sdk, which can't use other libs.
 add_library(Udf STATIC ${PYTHON_UDF_SOURCES})
+
+# Unity build: eight homogeneous python-UDF glue TUs sharing the Python/arrow
+# header closure; batch 0 merges them into a single unity TU.
+set_target_properties(Udf PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                     UNITY_BUILD_BATCH_SIZE 0)
diff --git a/be/src/util/CMakeLists.txt b/be/src/util/CMakeLists.txt
index f23c3ad865c..8941a7ed57f 100644
--- a/be/src/util/CMakeLists.txt
+++ b/be/src/util/CMakeLists.txt
@@ -41,3 +41,22 @@ add_library(Util STATIC
 )
 
 pch_reuse(Util)
+
+# Unity build for the small util TUs (parse-overhead dominated). Ten files
+# leak file-scope macros and stay individual; hash/city.cc keeps its generic
+# k0..k4 static hash constants away from sibling scopes. perf_counters.cpp
+# is a Linux-only member (macOS builds its _mac variant, which is clean).
+set(UTIL_UNITY_SKIP
+    ${CMAKE_CURRENT_SOURCE_DIR}/bfd_parser.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/hash/city.cc
+    ${CMAKE_CURRENT_SOURCE_DIR}/hash/murmur_hash3.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/network_util.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/os_info.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/os_util.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/perf_counters.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/simd/parquet_kernels.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/thrift_util.cpp
+    ${CMAKE_CURRENT_SOURCE_DIR}/zlib.cpp)
+doris_skip_unity_inclusion(${UTIL_UNITY_SKIP})
+set_target_properties(Util PROPERTIES UNITY_BUILD ${DORIS_UNITY_BUILD}
+                                      UNITY_BUILD_BATCH_SIZE 24)
diff --git a/be/src/util/bvar_windowed_adder.h 
b/be/src/util/bvar_windowed_adder.h
index c4e9245b7e3..f249dc3a198 100644
--- a/be/src/util/bvar_windowed_adder.h
+++ b/be/src/util/bvar_windowed_adder.h
@@ -33,6 +33,12 @@
 
 namespace doris {
 
+// Shared window spans (seconds) for multi-window metrics.
+// bvar::Window enforces MAX_SECONDS_LIMIT = 3600, so the longest window is 1h.
+inline constexpr int WINDOW_5M = 300;
+inline constexpr int WINDOW_30M = 1800;
+inline constexpr int WINDOW_1H = 3600;
+
 /**
  * Multi-dimension windowed adder.
  *
diff --git a/be/src/util/json/path_in_data.h b/be/src/util/json/path_in_data.h
index 593904dd931..2e549cb714a 100644
--- a/be/src/util/json/path_in_data.h
+++ b/be/src/util/json/path_in_data.h
@@ -135,6 +135,12 @@ private:
     bool is_typed = false;
 };
 
+// Heap bytes retained beyond sizeof(PathInData): the dotted-path string buffer
+// plus the parts vector.
+inline size_t path_allocated_bytes(const PathInData& path) {
+    return path.get_path().capacity() + path.get_parts().capacity() * 
sizeof(PathInData::Part);
+}
+
 class PathInDataBuilder {
 public:
     const PathInData::Parts& get_parts() const { return parts; }
diff --git a/be/src/util/sm3.cpp b/be/src/util/sm3.cpp
index 2d4349abc84..448f2365e5f 100644
--- a/be/src/util/sm3.cpp
+++ b/be/src/util/sm3.cpp
@@ -46,11 +46,11 @@ void SM3Digest::digest() {
 
     char hex_buf[2 * SM3_DIGEST_LENGTH];
 
-    static char dig_vec_lower[] = "0123456789abcdef";
+    static constexpr char sm3_dig_vec_lower[] = "0123456789abcdef";
     char* to = hex_buf;
     for (int i = 0; i < SM3_DIGEST_LENGTH; ++i) {
-        *to++ = dig_vec_lower[buf[i] >> 4];
-        *to++ = dig_vec_lower[buf[i] & 0x0F];
+        *to++ = sm3_dig_vec_lower[buf[i] >> 4];
+        *to++ = sm3_dig_vec_lower[buf[i] & 0x0F];
     }
     _hex.assign(hex_buf, 2 * SM3_DIGEST_LENGTH);
 }
diff --git a/be/src/util/timezone_utils.cpp b/be/src/util/timezone_utils.cpp
index b575ed7a29f..358d8b962cc 100644
--- a/be/src/util/timezone_utils.cpp
+++ b/be/src/util/timezone_utils.cpp
@@ -51,7 +51,7 @@ namespace doris {
 
 using ZoneList = std::unordered_map<std::string, cctz::time_zone>;
 
-RE2 time_zone_offset_format_reg(R"(^[+-]{1}\d{2}\:\d{2}$)"); // visiting is 
thread-safe
+static RE2 tz_offset_format_reg(R"(^[+-]{1}\d{2}\:\d{2}$)"); // visiting is 
thread-safe
 
 // for ut, make it never nullptr.
 std::unique_ptr<ZoneList> lower_zone_cache_ = std::make_unique<ZoneList>();
@@ -277,8 +277,8 @@ bool TimezoneUtils::parse_tz_offset_string(const 
std::string& timezone, cctz::ti
     }
 
     re2::StringPiece value;
-    if (time_zone_offset_format_reg.Match(normalized, 0, normalized.size(), 
RE2::UNANCHORED, &value,
-                                          1)) [[likely]] {
+    if (tz_offset_format_reg.Match(normalized, 0, normalized.size(), 
RE2::UNANCHORED, &value, 1))
+            [[likely]] {
         const bool positive = value[0] != '-';
         const int hour = std::stoi(value.substr(1, 2).as_string());
         const int minute = std::stoi(value.substr(4, 2).as_string());
diff --git a/be/test/io/cache/fs_file_cache_storage_leak_cleaner_test.cpp 
b/be/test/io/cache/fs_file_cache_storage_leak_cleaner_test.cpp
index a4b5035ad45..0ab9953cb54 100644
--- a/be/test/io/cache/fs_file_cache_storage_leak_cleaner_test.cpp
+++ b/be/test/io/cache/fs_file_cache_storage_leak_cleaner_test.cpp
@@ -131,8 +131,10 @@ protected:
             BlockMetaKey mkey(0, hash, offset);
             BlockMeta meta(FileCacheType::NORMAL, 16, 0);
             storage._meta_store->put(mkey, meta);
-            // Wait for async write to complete for test stability
-            for (int i = 0; i < 100 && 
storage._meta_store->get_write_queue_size() > 0; ++i) {
+            // The async worker dequeues an operation before it lands in 
rocksdb,
+            // so an empty write queue does not mean the entry is readable yet.
+            // Poll the store itself: leak-scan decisions count rocksdb 
contents.
+            for (int i = 0; i < 100 && 
!storage._meta_store->get(mkey).has_value(); ++i) {
                 std::this_thread::sleep_for(std::chrono::milliseconds(50));
             }
         }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to