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 07f911248e6 [opt](build) Declare extern template for existing explicit
instantiations (#66807)
07f911248e6 is described below
commit 07f911248e65f785510ac0d039609b0229f688f1
Author: Mingyu Chen (Rayner) <[email protected]>
AuthorDate: Mon Aug 17 11:02:32 2026 +0800
[opt](build) Declare extern template for existing explicit instantiations
(#66807)
> Part of the BE build-time optimization series tracked in #66715.
>
> Split out of **https://github.com/apache/doris/pull/66510**. With the
include-edge
> surgery (#66400, #66672) and the unity-build line (#66712, #66776,
#66789) merged,
> this PR opens the third mechanism of the batch: making the **explicit
template
> instantiations we already have** actually pay for themselves by
declaring them
> `extern template` in the headers.
### What problem does this PR solve?
Related PR: #66510, #66789
Problem Summary:
`be/src` already contains ~221 `template class` **explicit instantiation
definitions** (columns, DataTypes, SerDes, the operator families, …).
But almost
none of them are announced in the corresponding headers with an
`extern template` declaration. The result: every consumer TU that
touches
`ColumnVector<T>` / `DataTypeDecimalSerDe<T>` / `AsyncWriterSink<W, P>`
still
**implicitly instantiates the whole class again**, compiles the member
functions
as weak symbols, and the linker then throws all the duplicates away. The
explicit-instantiation TU does the same work one more time. We pay the
template
instantiation cost N+1 times and keep exactly one copy.
`extern template` is the standard C++11 tool for this: it suppresses
implicit
instantiation in consumers and pins code generation to the one TU that
already
carries the explicit definition. **It changes symbol ownership only, not
generated code** — a consumer TU compiled before/after this PR produces
byte-identical code for its own functions (verified on a control TU
during the
original measurement round).
What the commits do:
1. **Column classes** (`column_vector.h` 18, `column_decimal.h` 5,
`column_string.h` 2): declare extern the 25 instantiations defined in
the
matching `.cpp` files.
2. **DataType / SerDe surface** (6 headers): 47 externs for the
date/datetime/decimal/number/string SerDe instantiation sets.
3. **Exec operator families** (39 headers, 99 externs):
`AsyncWriterSink`,
`DataSinkOperatorX`, `OperatorX`, partitioners,
aggregation/table-function
operators — all instantiated centrally (mostly in `operator.cpp`) since
the
operator refactor, never externed.
4. **Narrow surfaces** (17 headers, 75 externs): parquet/orc readers,
segment
iterators, frame-of-reference coding, phrase queries, JSON parser.
5. **`DataTypeNumber<T>`**: the base class was explicitly instantiated
but the
derived class itself was not — instantiations existed nowhere, so every
user
built the full class. Adds the 8 explicit definitions in
`data_type_number_base.cpp` plus matching externs.
6. **One-line correctness fix** the externs exposed:
`inverted_index_writer.h`
forward-declared `CppTypeTraits` itself; triggering class-level
instantiation
from the extern requires the real definition, and exactly one storage
unity
batch (of 13k+ TUs) lacked it transitively. Include `storage/types.h`
directly.
### Measured results
Numbers below were taken on the original development branch **before the
unity
line landed** (macOS arm64, clang 20, `-j6`, no PCH for the sentinel
probes),
because that is where the mechanism was isolated. Landing after unity
(#66789), part of the win is already absorbed — sibling files inside one
unity
batch share a single implicit instantiation — so the remaining surface
here is
the SKIP-listed heavy individual TUs, cross-batch dedup, and the BE UT
tree:
| metric | before | after |
|---|---|---|
| full cold build (`-j6`) | 33m15s | **32m36s (−2.0%)** |
| `multiply.cpp` sentinel TU (no PCH) | 78.7s | **73.0s (−7.3%)** |
| `plus.cpp` sentinel TU (no PCH) | 56.3s | **52.0s (−7.6%)** |
| weak-symbol overlap multiply∩plus | 1552 | **491 (−68%)** |
| `doris_be` size (pre-unity layout) | 1856MB | **1809MB (−2.5%)** |
Validation of this PR's tree (master + these 6 commits, macOS arm64
clang20,
unity=ON + PCH=ON):
- full BE build: 7446/7446 edges, **zero failures**, `doris_be` links at
319MB
(same as current master);
- static pairing audit: all **266 `extern template` declarations** added
here
resolve to an existing explicit instantiation definition in the current
tree;
- BE UT (`BUILD_TYPE_UT=Debug`): 8501/8501 edges compiled,
`doris_be_test`
links with **zero duplicate/undefined symbols** — the sensitive surface
for
an extern-template change, since tests link the full static-library set;
- `git clang-format` clean against master.
### Methodology, and what we deliberately did NOT extern
The go/no-go gauge for each candidate was **weak symbols owned by
consumer
`.o` files** (`llvm-nm -C | grep ' [VvWw] '` filtered by the class
prefix), not
the count of instantiation statements. By that gauge three whole
families were
rejected as free-of-benefit and are intentionally absent here:
- `Allocator` (48 instantiation sites): consumers own ≈0 weak symbols of
it;
- `PODArray`: same;
- `COWHelper` base-class instantiations: same.
Three further individual candidates were dropped because their include
topology would have needed real surgery for a mechanism whose gain there
is ≈0.
### Risks / disclosures
- **Runtime impact: none by construction.** `extern template` moves
symbol
ownership; it does not change what code is generated for the anchor TU,
and
inline/constexpr members remain inlinable at call sites exactly as
before.
- **Cross-platform**: all local validation is macOS/clang20. gcc handles
`extern template` + in-class-defined members slightly differently in
diagnostics; the Performance pipeline (the only gcc lane) is the
authoritative check. Please watch its first round.
- The `DORIS_DEV_DEBUG_INFO` developer knob that rode along in the
original
branch is intentionally **not** in this PR (unrelated mechanism, will be
proposed separately).
---------
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
be/src/core/column/column_decimal.h | 7 ++++
be/src/core/column/column_string.h | 5 +++
be/src/core/column/column_vector.h | 20 +++++++++++
be/src/core/data_type/data_type_decimal.h | 7 ++++
be/src/core/data_type/data_type_number.h | 10 ++++++
be/src/core/data_type/data_type_number_base.cpp | 10 ++++++
be/src/core/data_type/data_type_number_base.h | 19 ++++++++++
.../data_type_date_or_datetime_serde.h | 6 ++++
.../core/data_type_serde/data_type_decimal_serde.h | 10 ++++--
.../core/data_type_serde/data_type_number_serde.h | 18 ++++++++++
.../core/data_type_serde/data_type_string_serde.h | 6 ++++
be/src/core/value/vdatetime_value.h | 5 +++
be/src/exec/operator/analytic_sink_operator.h | 4 +++
be/src/exec/operator/assert_num_rows_operator.h | 3 ++
.../distinct_streaming_aggregation_operator.h | 3 ++
be/src/exec/operator/file_scan_operator.h | 4 +++
be/src/exec/operator/group_commit_scan_operator.h | 4 +++
be/src/exec/operator/hashjoin_build_sink.h | 5 +++
be/src/exec/operator/hashjoin_probe_operator.h | 6 ++++
be/src/exec/operator/hive_table_sink_operator.h | 3 ++
.../exec/operator/iceberg_delete_sink_operator.h | 3 ++
be/src/exec/operator/iceberg_merge_sink_operator.h | 3 ++
be/src/exec/operator/iceberg_table_sink_operator.h | 3 ++
be/src/exec/operator/jdbc_scan_operator.h | 4 +++
be/src/exec/operator/jdbc_table_sink_operator.h | 3 ++
be/src/exec/operator/materialization_opertor.h | 3 ++
.../exec/operator/maxcompute_table_sink_operator.h | 3 ++
be/src/exec/operator/meta_scan_operator.h | 4 +++
be/src/exec/operator/mock_scan_operator.h | 5 +++
.../operator/nested_loop_join_build_operator.h | 6 ++++
.../operator/nested_loop_join_probe_operator.h | 6 ++++
be/src/exec/operator/olap_scan_operator.h | 4 +++
be/src/exec/operator/olap_table_sink_operator.h | 3 ++
be/src/exec/operator/olap_table_sink_v2_operator.h | 3 ++
be/src/exec/operator/operator.h | 40 ++++++++++++++++++++++
.../partitioned_hash_join_probe_operator.h | 7 ++++
.../operator/partitioned_hash_join_sink_operator.h | 6 ++++
.../exec/operator/rec_cte_anchor_sink_operator.h | 3 ++
be/src/exec/operator/rec_cte_sink_operator.h | 3 ++
be/src/exec/operator/rec_cte_source_operator.h | 3 ++
be/src/exec/operator/repeat_operator.h | 3 ++
be/src/exec/operator/result_file_sink_operator.h | 3 ++
be/src/exec/operator/select_operator.h | 3 ++
be/src/exec/operator/set_probe_sink_operator.h | 7 ++++
be/src/exec/operator/set_sink_operator.h | 6 ++++
be/src/exec/operator/set_source_operator.h | 7 ++++
.../operator/spill_iceberg_table_sink_operator.h | 3 ++
.../exec/operator/streaming_aggregation_operator.h | 3 ++
be/src/exec/operator/table_function_operator.h | 3 ++
be/src/exec/operator/tvf_table_sink_operator.h | 3 ++
be/src/exec/partitioner/partitioner.h | 5 +++
be/src/exprs/table_function/vjson_each.h | 4 +++
.../format/parquet/vparquet_column_chunk_reader.h | 6 ++++
be/src/format/parquet/vparquet_column_reader.h | 6 ++++
be/src/format/parquet/vparquet_page_reader.h | 6 ++++
.../parquet/reader/native/column_chunk_reader.h | 6 ++++
.../parquet/reader/native/column_reader.h | 6 ++++
.../format_v2/parquet/reader/native/page_reader.h | 6 ++++
be/src/storage/cache/page_cache.h | 3 ++
.../storage/index/inverted/inverted_index_writer.h | 30 ++++++++++++++--
.../query_v2/boolean_query/occur_boolean_weight.h | 5 +++
.../index/inverted/query_v2/disjunction_scorer.h | 5 +++
.../index/inverted/query_v2/exclude_scorer.h | 3 ++
.../inverted/query_v2/phrase_query/phrase_scorer.h | 4 +++
.../index/inverted/query_v2/union/simple_union.h | 5 +++
be/src/util/frame_of_reference_coding.h | 28 +++++++++++++++
be/src/util/json/json_parser.h | 4 +++
67 files changed, 438 insertions(+), 5 deletions(-)
diff --git a/be/src/core/column/column_decimal.h
b/be/src/core/column/column_decimal.h
index 9d6ec34c8b8..8cd7be991a7 100644
--- a/be/src/core/column/column_decimal.h
+++ b/be/src/core/column/column_decimal.h
@@ -306,4 +306,11 @@ using ColumnDecimal128V2 = ColumnDecimal<TYPE_DECIMALV2>;
using ColumnDecimal128V3 = ColumnDecimal<TYPE_DECIMAL128I>;
using ColumnDecimal256 = ColumnDecimal<TYPE_DECIMAL256>;
+/// Instantiated once in column_decimal.cpp; suppresses per-TU implicit
instantiation.
+extern template class ColumnDecimal<TYPE_DECIMAL32>;
+extern template class ColumnDecimal<TYPE_DECIMAL64>;
+extern template class ColumnDecimal<TYPE_DECIMALV2>;
+extern template class ColumnDecimal<TYPE_DECIMAL128I>;
+extern template class ColumnDecimal<TYPE_DECIMAL256>;
+
} // namespace doris
diff --git a/be/src/core/column/column_string.h
b/be/src/core/column/column_string.h
index 616d6ef9df3..54d224c0c22 100644
--- a/be/src/core/column/column_string.h
+++ b/be/src/core/column/column_string.h
@@ -656,4 +656,9 @@ public:
using ColumnString = ColumnStr<UInt32>;
using ColumnString64 = ColumnStr<UInt64>;
+
+/// Instantiated once in column_string.cpp; suppresses per-TU implicit
instantiation.
+extern template class ColumnStr<UInt32>;
+extern template class ColumnStr<UInt64>;
+
} // namespace doris
diff --git a/be/src/core/column/column_vector.h
b/be/src/core/column/column_vector.h
index 4f3a7a6c46f..5c6b6f294f5 100644
--- a/be/src/core/column/column_vector.h
+++ b/be/src/core/column/column_vector.h
@@ -446,4 +446,24 @@ using ColumnTimeStampTz = ColumnVector<TYPE_TIMESTAMPTZ>;
using ColumnOffset32 = ColumnVector<TYPE_UINT32>;
using ColumnOffset64 = ColumnVector<TYPE_UINT64>;
+/// Instantiated once in column_vector.cpp; suppresses per-TU implicit
instantiation.
+extern template class ColumnVector<TYPE_BOOLEAN>;
+extern template class ColumnVector<TYPE_TINYINT>;
+extern template class ColumnVector<TYPE_SMALLINT>;
+extern template class ColumnVector<TYPE_INT>;
+extern template class ColumnVector<TYPE_BIGINT>;
+extern template class ColumnVector<TYPE_LARGEINT>;
+extern template class ColumnVector<TYPE_FLOAT>;
+extern template class ColumnVector<TYPE_DOUBLE>;
+extern template class ColumnVector<TYPE_IPV4>;
+extern template class ColumnVector<TYPE_IPV6>;
+extern template class ColumnVector<TYPE_DATE>;
+extern template class ColumnVector<TYPE_DATEV2>;
+extern template class ColumnVector<TYPE_DATETIME>;
+extern template class ColumnVector<TYPE_DATETIMEV2>;
+extern template class ColumnVector<TYPE_TIMEV2>;
+extern template class ColumnVector<TYPE_TIMESTAMPTZ>;
+extern template class ColumnVector<TYPE_UINT32>;
+extern template class ColumnVector<TYPE_UINT64>;
+
} // namespace doris
diff --git a/be/src/core/data_type/data_type_decimal.h
b/be/src/core/data_type/data_type_decimal.h
index 69fae16be82..a863316cbce 100644
--- a/be/src/core/data_type/data_type_decimal.h
+++ b/be/src/core/data_type/data_type_decimal.h
@@ -526,4 +526,11 @@
static_assert(!has_original_precision_and_scale<DataTypeDecimal64>);
static_assert(!has_original_precision_and_scale<DataTypeDecimal128>);
static_assert(!has_original_precision_and_scale<DataTypeDecimal256>);
+/// Instantiated once in data_type_decimal.cpp; suppresses per-TU implicit
instantiation.
+extern template class DataTypeDecimal<TYPE_DECIMAL32>;
+extern template class DataTypeDecimal<TYPE_DECIMAL64>;
+extern template class DataTypeDecimal<TYPE_DECIMALV2>;
+extern template class DataTypeDecimal<TYPE_DECIMAL128I>;
+extern template class DataTypeDecimal<TYPE_DECIMAL256>;
+
} // namespace doris
diff --git a/be/src/core/data_type/data_type_number.h
b/be/src/core/data_type/data_type_number.h
index 99b8bb42880..87d9ae925c7 100644
--- a/be/src/core/data_type/data_type_number.h
+++ b/be/src/core/data_type/data_type_number.h
@@ -77,4 +77,14 @@ inline constexpr bool IsDataTypeFloat<DataTypeFloat32> =
true;
template <>
inline constexpr bool IsDataTypeFloat<DataTypeFloat64> = true;
+/// Instantiated once in data_type_number_base.cpp; suppresses per-TU implicit
instantiation.
+extern template class DataTypeNumber<TYPE_BOOLEAN>;
+extern template class DataTypeNumber<TYPE_TINYINT>;
+extern template class DataTypeNumber<TYPE_SMALLINT>;
+extern template class DataTypeNumber<TYPE_INT>;
+extern template class DataTypeNumber<TYPE_BIGINT>;
+extern template class DataTypeNumber<TYPE_LARGEINT>;
+extern template class DataTypeNumber<TYPE_FLOAT>;
+extern template class DataTypeNumber<TYPE_DOUBLE>;
+
} // namespace doris
diff --git a/be/src/core/data_type/data_type_number_base.cpp
b/be/src/core/data_type/data_type_number_base.cpp
index dcd167bce1d..5f60f7afcbb 100644
--- a/be/src/core/data_type/data_type_number_base.cpp
+++ b/be/src/core/data_type/data_type_number_base.cpp
@@ -36,6 +36,7 @@
#include "core/column/column.h"
#include "core/column/column_const.h"
#include "core/column/column_vector.h"
+#include "core/data_type/data_type_number.h"
#include "core/data_type/primitive_type.h"
#include "core/string_buffer.hpp"
#include "core/types.h"
@@ -208,4 +209,13 @@ template class DataTypeNumberBase<TYPE_IPV6>;
template class DataTypeNumberBase<TYPE_TIMEV2>;
template class DataTypeNumberBase<TYPE_TIMESTAMPTZ>;
+template class DataTypeNumber<TYPE_BOOLEAN>;
+template class DataTypeNumber<TYPE_TINYINT>;
+template class DataTypeNumber<TYPE_SMALLINT>;
+template class DataTypeNumber<TYPE_INT>;
+template class DataTypeNumber<TYPE_BIGINT>;
+template class DataTypeNumber<TYPE_LARGEINT>;
+template class DataTypeNumber<TYPE_FLOAT>;
+template class DataTypeNumber<TYPE_DOUBLE>;
+
} // namespace doris
diff --git a/be/src/core/data_type/data_type_number_base.h
b/be/src/core/data_type/data_type_number_base.h
index f3fe2544196..63fd4968583 100644
--- a/be/src/core/data_type/data_type_number_base.h
+++ b/be/src/core/data_type/data_type_number_base.h
@@ -94,4 +94,23 @@ protected:
private:
bool _is_null_literal = false;
};
+
+/// Instantiated once in data_type_number_base.cpp; suppresses per-TU implicit
instantiation.
+extern template class DataTypeNumberBase<TYPE_BOOLEAN>;
+extern template class DataTypeNumberBase<TYPE_TINYINT>;
+extern template class DataTypeNumberBase<TYPE_SMALLINT>;
+extern template class DataTypeNumberBase<TYPE_INT>;
+extern template class DataTypeNumberBase<TYPE_BIGINT>;
+extern template class DataTypeNumberBase<TYPE_LARGEINT>;
+extern template class DataTypeNumberBase<TYPE_FLOAT>;
+extern template class DataTypeNumberBase<TYPE_DOUBLE>;
+extern template class DataTypeNumberBase<TYPE_DATE>;
+extern template class DataTypeNumberBase<TYPE_DATEV2>;
+extern template class DataTypeNumberBase<TYPE_DATETIME>;
+extern template class DataTypeNumberBase<TYPE_DATETIMEV2>;
+extern template class DataTypeNumberBase<TYPE_IPV4>;
+extern template class DataTypeNumberBase<TYPE_IPV6>;
+extern template class DataTypeNumberBase<TYPE_TIMEV2>;
+extern template class DataTypeNumberBase<TYPE_TIMESTAMPTZ>;
+
} // namespace doris
diff --git a/be/src/core/data_type_serde/data_type_date_or_datetime_serde.h
b/be/src/core/data_type_serde/data_type_date_or_datetime_serde.h
index 693bfca7385..e8ce3f41069 100644
--- a/be/src/core/data_type_serde/data_type_date_or_datetime_serde.h
+++ b/be/src/core/data_type_serde/data_type_date_or_datetime_serde.h
@@ -145,4 +145,10 @@ public:
Status read_column_from_arrow(IColumn& column, const arrow::Array*
arrow_array, int64_t start,
int64_t end, const cctz::time_zone& ctz)
const override;
};
+
+/// Instantiated once in data_type_date_or_datetime_serde.cpp; suppresses
per-TU implicit
+/// instantiation.
+extern template class DataTypeDateSerDe<TYPE_DATE>;
+extern template class DataTypeDateSerDe<TYPE_DATETIME>;
+
} // namespace doris
diff --git a/be/src/core/data_type_serde/data_type_decimal_serde.h
b/be/src/core/data_type_serde/data_type_decimal_serde.h
index b475923c83f..424c837a7ca 100644
--- a/be/src/core/data_type_serde/data_type_decimal_serde.h
+++ b/be/src/core/data_type_serde/data_type_decimal_serde.h
@@ -25,6 +25,7 @@
#include "common/status.h"
#include "core/column/column.h"
#include "core/column/column_const.h"
+#include "core/column/column_decimal.h"
#include "core/data_type/define_primitive_type.h"
#include "core/data_type_serde/data_type_serde.h"
#include "core/string_ref.h"
@@ -32,8 +33,6 @@
namespace doris {
-template <PrimitiveType T>
-class ColumnDecimal;
class Arena;
template <PrimitiveType T>
@@ -219,4 +218,11 @@ Status
DataTypeDecimalSerDe<T>::read_column_from_pb(IColumn& column, const PValu
return Status::OK();
}
+/// Instantiated once in data_type_decimal_serde.cpp; suppresses per-TU
implicit instantiation.
+extern template class DataTypeDecimalSerDe<TYPE_DECIMAL32>;
+extern template class DataTypeDecimalSerDe<TYPE_DECIMAL64>;
+extern template class DataTypeDecimalSerDe<TYPE_DECIMAL128I>;
+extern template class DataTypeDecimalSerDe<TYPE_DECIMALV2>;
+extern template class DataTypeDecimalSerDe<TYPE_DECIMAL256>;
+
} // namespace doris
diff --git a/be/src/core/data_type_serde/data_type_number_serde.h
b/be/src/core/data_type_serde/data_type_number_serde.h
index 9c0de8cb0c0..2090a5d936a 100644
--- a/be/src/core/data_type_serde/data_type_number_serde.h
+++ b/be/src/core/data_type_serde/data_type_number_serde.h
@@ -348,4 +348,22 @@ Status DataTypeNumberSerDe<T>::write_column_to_pb(const
IColumn& column, PValues
return Status::OK();
}
+/// Instantiated once in data_type_number_serde.cpp; suppresses per-TU
implicit instantiation.
+extern template class DataTypeNumberSerDe<TYPE_BOOLEAN>;
+extern template class DataTypeNumberSerDe<TYPE_TINYINT>;
+extern template class DataTypeNumberSerDe<TYPE_SMALLINT>;
+extern template class DataTypeNumberSerDe<TYPE_INT>;
+extern template class DataTypeNumberSerDe<TYPE_BIGINT>;
+extern template class DataTypeNumberSerDe<TYPE_LARGEINT>;
+extern template class DataTypeNumberSerDe<TYPE_FLOAT>;
+extern template class DataTypeNumberSerDe<TYPE_DOUBLE>;
+extern template class DataTypeNumberSerDe<TYPE_DATE>;
+extern template class DataTypeNumberSerDe<TYPE_DATEV2>;
+extern template class DataTypeNumberSerDe<TYPE_DATETIME>;
+extern template class DataTypeNumberSerDe<TYPE_DATETIMEV2>;
+extern template class DataTypeNumberSerDe<TYPE_IPV4>;
+extern template class DataTypeNumberSerDe<TYPE_IPV6>;
+extern template class DataTypeNumberSerDe<TYPE_TIMEV2>;
+extern template class DataTypeNumberSerDe<TYPE_TIMESTAMPTZ>;
+
} // namespace doris
diff --git a/be/src/core/data_type_serde/data_type_string_serde.h
b/be/src/core/data_type_serde/data_type_string_serde.h
index c81f6d37aa4..5a95816243a 100644
--- a/be/src/core/data_type_serde/data_type_string_serde.h
+++ b/be/src/core/data_type_serde/data_type_string_serde.h
@@ -282,4 +282,10 @@ private:
using DataTypeStringSerDe = DataTypeStringSerDeBase<ColumnString>;
using DataTypeFixedLengthObjectSerDe =
DataTypeStringSerDeBase<ColumnFixedLengthObject>;
+
+/// Instantiated once in data_type_string_serde.cpp; suppresses per-TU
implicit instantiation.
+extern template class DataTypeStringSerDeBase<ColumnString>;
+extern template class DataTypeStringSerDeBase<ColumnString64>;
+extern template class DataTypeStringSerDeBase<ColumnFixedLengthObject>;
+
} // namespace doris
diff --git a/be/src/core/value/vdatetime_value.h
b/be/src/core/value/vdatetime_value.h
index da0bba19bcb..e906c4f842a 100644
--- a/be/src/core/value/vdatetime_value.h
+++ b/be/src/core/value/vdatetime_value.h
@@ -1804,6 +1804,11 @@ struct DateTraits<uint64_t> {
using DateType = DataTypeDateTimeV2;
};
#include "common/compile_check_avoid_end.h"
+
+/// Instantiated once in vdatetime_value.cpp; suppresses per-TU implicit
instantiation.
+extern template class DateV2Value<DateV2ValueType>;
+extern template class DateV2Value<DateTimeV2ValueType>;
+
} // namespace doris
template <>
diff --git a/be/src/exec/operator/analytic_sink_operator.h
b/be/src/exec/operator/analytic_sink_operator.h
index 488bdc156f0..dfed9476b49 100644
--- a/be/src/exec/operator/analytic_sink_operator.h
+++ b/be/src/exec/operator/analytic_sink_operator.h
@@ -267,4 +267,8 @@ private:
std::vector<bool> _change_to_nullable_flags;
};
+/// Instantiated once in analytic_sink_operator.cpp; suppresses per-TU implicit
+/// instantiation.
+extern template class DataSinkOperatorX<AnalyticSinkLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/assert_num_rows_operator.h
b/be/src/exec/operator/assert_num_rows_operator.h
index 4c71266c626..0a7417abffc 100644
--- a/be/src/exec/operator/assert_num_rows_operator.h
+++ b/be/src/exec/operator/assert_num_rows_operator.h
@@ -59,4 +59,7 @@ private:
bool _should_convert_output_to_nullable;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class StreamingOperatorX<AssertNumRowsLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/distinct_streaming_aggregation_operator.h
b/be/src/exec/operator/distinct_streaming_aggregation_operator.h
index a5c2f46c267..3d5304aff1e 100644
--- a/be/src/exec/operator/distinct_streaming_aggregation_operator.h
+++ b/be/src/exec/operator/distinct_streaming_aggregation_operator.h
@@ -161,4 +161,7 @@ private:
bool _is_streaming_preagg = false;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class StatefulOperatorX<DistinctStreamingAggLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/file_scan_operator.h
b/be/src/exec/operator/file_scan_operator.h
index 7d8fae51b78..ac422a4e6af 100644
--- a/be/src/exec/operator/file_scan_operator.h
+++ b/be/src/exec/operator/file_scan_operator.h
@@ -132,4 +132,8 @@ private:
bool _batch_split_mode = false;
};
+/// Instantiated once in scan_operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class ScanOperatorX<FileScanLocalState>;
+extern template class ScanLocalState<FileScanLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/group_commit_scan_operator.h
b/be/src/exec/operator/group_commit_scan_operator.h
index 679b46b1125..0b43554c673 100644
--- a/be/src/exec/operator/group_commit_scan_operator.h
+++ b/be/src/exec/operator/group_commit_scan_operator.h
@@ -61,4 +61,8 @@ protected:
const int64_t _table_id;
};
+/// Instantiated once in scan_operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class ScanOperatorX<GroupCommitLocalState>;
+extern template class ScanLocalState<GroupCommitLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/hashjoin_build_sink.h
b/be/src/exec/operator/hashjoin_build_sink.h
index 3550f77c752..a7df04eddb8 100644
--- a/be/src/exec/operator/hashjoin_build_sink.h
+++ b/be/src/exec/operator/hashjoin_build_sink.h
@@ -277,4 +277,9 @@ private:
RuntimeState* _state = nullptr;
};
+/// Instantiated once in join_build_sink_operator.cpp; suppresses per-TU
implicit
+/// instantiation.
+extern template class JoinBuildSinkOperatorX<HashJoinBuildSinkLocalState>;
+extern template class JoinBuildSinkLocalState<HashJoinSharedState,
HashJoinBuildSinkLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/hashjoin_probe_operator.h
b/be/src/exec/operator/hashjoin_probe_operator.h
index 2542efe9c88..903a9209c46 100644
--- a/be/src/exec/operator/hashjoin_probe_operator.h
+++ b/be/src/exec/operator/hashjoin_probe_operator.h
@@ -220,4 +220,10 @@ private:
size_t _right_col_idx;
};
+/// Instantiated once in operator.cpp / join_probe_operator.cpp; suppresses
per-TU
+/// implicit instantiation.
+extern template class StatefulOperatorX<HashJoinProbeLocalState>;
+extern template class JoinProbeLocalState<HashJoinSharedState,
HashJoinProbeLocalState>;
+extern template class JoinProbeOperatorX<HashJoinProbeLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/hive_table_sink_operator.h
b/be/src/exec/operator/hive_table_sink_operator.h
index 51161809e68..ffb331064bf 100644
--- a/be/src/exec/operator/hive_table_sink_operator.h
+++ b/be/src/exec/operator/hive_table_sink_operator.h
@@ -83,4 +83,7 @@ private:
ObjectPool* _pool = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VHiveTableWriter,
HiveTableSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/iceberg_delete_sink_operator.h
b/be/src/exec/operator/iceberg_delete_sink_operator.h
index 12f93bfc8b6..25167f4236e 100644
--- a/be/src/exec/operator/iceberg_delete_sink_operator.h
+++ b/be/src/exec/operator/iceberg_delete_sink_operator.h
@@ -82,4 +82,7 @@ private:
ObjectPool* _pool = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VIcebergDeleteSink,
IcebergDeleteSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/iceberg_merge_sink_operator.h
b/be/src/exec/operator/iceberg_merge_sink_operator.h
index 0cf64681c1d..5d48911ad8e 100644
--- a/be/src/exec/operator/iceberg_merge_sink_operator.h
+++ b/be/src/exec/operator/iceberg_merge_sink_operator.h
@@ -81,4 +81,7 @@ private:
ObjectPool* _pool = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VIcebergMergeSink,
IcebergMergeSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/iceberg_table_sink_operator.h
b/be/src/exec/operator/iceberg_table_sink_operator.h
index 0dec306edeb..a91950af7a7 100644
--- a/be/src/exec/operator/iceberg_table_sink_operator.h
+++ b/be/src/exec/operator/iceberg_table_sink_operator.h
@@ -82,4 +82,7 @@ private:
ObjectPool* _pool = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VIcebergTableWriter,
IcebergTableSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/jdbc_scan_operator.h
b/be/src/exec/operator/jdbc_scan_operator.h
index feb11ff331a..696da3df26e 100644
--- a/be/src/exec/operator/jdbc_scan_operator.h
+++ b/be/src/exec/operator/jdbc_scan_operator.h
@@ -61,4 +61,8 @@ private:
bool _is_tvf;
};
+/// Instantiated once in scan_operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class ScanOperatorX<JDBCScanLocalState>;
+extern template class ScanLocalState<JDBCScanLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/jdbc_table_sink_operator.h
b/be/src/exec/operator/jdbc_table_sink_operator.h
index a557ec80a8d..1c339119671 100644
--- a/be/src/exec/operator/jdbc_table_sink_operator.h
+++ b/be/src/exec/operator/jdbc_table_sink_operator.h
@@ -58,4 +58,7 @@ private:
VExprContextSPtrs _output_vexpr_ctxs;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VJdbcTableWriter,
JdbcTableSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/materialization_opertor.h
b/be/src/exec/operator/materialization_opertor.h
index 7dfdf69f823..1390aae0bdc 100644
--- a/be/src/exec/operator/materialization_opertor.h
+++ b/be/src/exec/operator/materialization_opertor.h
@@ -151,4 +151,7 @@ private:
VExprContextSPtrs _rowid_exprs;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class StatefulOperatorX<MaterializationLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/maxcompute_table_sink_operator.h
b/be/src/exec/operator/maxcompute_table_sink_operator.h
index 3332143080b..c1aebf8004f 100644
--- a/be/src/exec/operator/maxcompute_table_sink_operator.h
+++ b/be/src/exec/operator/maxcompute_table_sink_operator.h
@@ -80,4 +80,7 @@ private:
ObjectPool* _pool = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VMCTableWriter, MCTableSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/meta_scan_operator.h
b/be/src/exec/operator/meta_scan_operator.h
index 05829c76a19..e14e9282f4f 100644
--- a/be/src/exec/operator/meta_scan_operator.h
+++ b/be/src/exec/operator/meta_scan_operator.h
@@ -63,4 +63,8 @@ private:
TUserIdentity _user_identity;
};
+/// Instantiated once in scan_operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class ScanOperatorX<MetaScanLocalState>;
+extern template class ScanLocalState<MetaScanLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/mock_scan_operator.h
b/be/src/exec/operator/mock_scan_operator.h
index 3eaa78366a8..609e631ce8c 100644
--- a/be/src/exec/operator/mock_scan_operator.h
+++ b/be/src/exec/operator/mock_scan_operator.h
@@ -102,5 +102,10 @@ public:
private:
std::list<Block> _output_blocks;
};
+
+/// Instantiated once in scan_operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class ScanOperatorX<MockScanLocalState>;
+extern template class ScanLocalState<MockScanLocalState>;
+
} // namespace doris
#endif
diff --git a/be/src/exec/operator/nested_loop_join_build_operator.h
b/be/src/exec/operator/nested_loop_join_build_operator.h
index 6001d05af29..ba91a60486b 100644
--- a/be/src/exec/operator/nested_loop_join_build_operator.h
+++ b/be/src/exec/operator/nested_loop_join_build_operator.h
@@ -82,4 +82,10 @@ private:
RowDescriptor _row_descriptor;
};
+/// Instantiated once in join_build_sink_operator.cpp; suppresses per-TU
implicit
+/// instantiation.
+extern template class
JoinBuildSinkOperatorX<NestedLoopJoinBuildSinkLocalState>;
+extern template class JoinBuildSinkLocalState<NestedLoopJoinSharedState,
+
NestedLoopJoinBuildSinkLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/nested_loop_join_probe_operator.h
b/be/src/exec/operator/nested_loop_join_probe_operator.h
index 02a51e91dbc..b9d283c18ad 100644
--- a/be/src/exec/operator/nested_loop_join_probe_operator.h
+++ b/be/src/exec/operator/nested_loop_join_probe_operator.h
@@ -308,4 +308,10 @@ private:
std::set<int> _materialize_column_ids;
};
+/// Instantiated once in operator.cpp / join_probe_operator.cpp; suppresses
per-TU
+/// implicit instantiation.
+extern template class StatefulOperatorX<NestedLoopJoinProbeLocalState>;
+extern template class JoinProbeLocalState<NestedLoopJoinSharedState,
NestedLoopJoinProbeLocalState>;
+extern template class JoinProbeOperatorX<NestedLoopJoinProbeLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/olap_scan_operator.h
b/be/src/exec/operator/olap_scan_operator.h
index 9f7ddca0527..46c65f06286 100644
--- a/be/src/exec/operator/olap_scan_operator.h
+++ b/be/src/exec/operator/olap_scan_operator.h
@@ -394,4 +394,8 @@ private:
TabletSchemaSPtr _tablet_schema;
};
+/// Instantiated once in scan_operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class ScanOperatorX<OlapScanLocalState>;
+extern template class ScanLocalState<OlapScanLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/olap_table_sink_operator.h
b/be/src/exec/operator/olap_table_sink_operator.h
index 9567b82e082..aad18fa3318 100644
--- a/be/src/exec/operator/olap_table_sink_operator.h
+++ b/be/src/exec/operator/olap_table_sink_operator.h
@@ -75,4 +75,7 @@ private:
ObjectPool* _pool = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VTabletWriter, OlapTableSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/olap_table_sink_v2_operator.h
b/be/src/exec/operator/olap_table_sink_v2_operator.h
index 038484c83ee..7ba63a1aad2 100644
--- a/be/src/exec/operator/olap_table_sink_v2_operator.h
+++ b/be/src/exec/operator/olap_table_sink_v2_operator.h
@@ -81,4 +81,7 @@ private:
ObjectPool* _pool = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VTabletWriterV2,
OlapTableSinkV2OperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/operator.h b/be/src/exec/operator/operator.h
index bb5cab376e6..5e23f737509 100644
--- a/be/src/exec/operator/operator.h
+++ b/be/src/exec/operator/operator.h
@@ -1260,4 +1260,44 @@ private:
};
#endif
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class PipelineXSinkLocalState<HashJoinSharedState>;
+extern template class PipelineXSinkLocalState<PartitionedHashJoinSharedState>;
+extern template class PipelineXSinkLocalState<SortSharedState>;
+extern template class PipelineXSinkLocalState<SpillSortSharedState>;
+extern template class PipelineXSinkLocalState<NestedLoopJoinSharedState>;
+extern template class PipelineXSinkLocalState<AnalyticSharedState>;
+extern template class PipelineXSinkLocalState<AggSharedState>;
+extern template class PipelineXSinkLocalState<BucketedAggSharedState>;
+extern template class PipelineXSinkLocalState<PartitionedAggSharedState>;
+extern template class PipelineXSinkLocalState<FakeSharedState>;
+extern template class PipelineXSinkLocalState<UnionSharedState>;
+extern template class PipelineXSinkLocalState<PartitionSortNodeSharedState>;
+extern template class PipelineXSinkLocalState<MultiCastSharedState>;
+extern template class PipelineXSinkLocalState<SetSharedState>;
+extern template class PipelineXSinkLocalState<LocalExchangeSharedState>;
+extern template class PipelineXSinkLocalState<BasicSharedState>;
+extern template class PipelineXSinkLocalState<DataQueueSharedState>;
+extern template class PipelineXLocalState<HashJoinSharedState>;
+extern template class PipelineXLocalState<PartitionedHashJoinSharedState>;
+extern template class PipelineXLocalState<SortSharedState>;
+extern template class PipelineXLocalState<SpillSortSharedState>;
+extern template class PipelineXLocalState<NestedLoopJoinSharedState>;
+extern template class PipelineXLocalState<AnalyticSharedState>;
+extern template class PipelineXLocalState<AggSharedState>;
+extern template class PipelineXLocalState<BucketedAggSharedState>;
+extern template class PipelineXLocalState<PartitionedAggSharedState>;
+extern template class PipelineXLocalState<FakeSharedState>;
+extern template class PipelineXLocalState<UnionSharedState>;
+extern template class PipelineXLocalState<DataQueueSharedState>;
+extern template class PipelineXLocalState<MultiCastSharedState>;
+extern template class PipelineXLocalState<PartitionSortNodeSharedState>;
+extern template class PipelineXLocalState<SetSharedState>;
+extern template class PipelineXLocalState<LocalExchangeSharedState>;
+extern template class PipelineXLocalState<BasicSharedState>;
+#ifdef BE_TEST
+extern template class OperatorX<DummyOperatorLocalState>;
+extern template class DataSinkOperatorX<DummySinkLocalState>;
+#endif
+
} // namespace doris
diff --git a/be/src/exec/operator/partitioned_hash_join_probe_operator.h
b/be/src/exec/operator/partitioned_hash_join_probe_operator.h
index 1a3564706c0..faaceda48e3 100644
--- a/be/src/exec/operator/partitioned_hash_join_probe_operator.h
+++ b/be/src/exec/operator/partitioned_hash_join_probe_operator.h
@@ -295,4 +295,11 @@ private:
int _repartition_max_depth = SpillRepartitioner::MAX_DEPTH;
};
+/// Instantiated once in operator.cpp / join_probe_operator.cpp; suppresses
per-TU
+/// implicit instantiation.
+extern template class StatefulOperatorX<PartitionedHashJoinProbeLocalState>;
+extern template class JoinProbeLocalState<PartitionedHashJoinSharedState,
+ PartitionedHashJoinProbeLocalState>;
+extern template class JoinProbeOperatorX<PartitionedHashJoinProbeLocalState>;
+
} // namespace doris
\ No newline at end of file
diff --git a/be/src/exec/operator/partitioned_hash_join_sink_operator.h
b/be/src/exec/operator/partitioned_hash_join_sink_operator.h
index bfa3d62a27b..4ad33dbcd05 100644
--- a/be/src/exec/operator/partitioned_hash_join_sink_operator.h
+++ b/be/src/exec/operator/partitioned_hash_join_sink_operator.h
@@ -181,4 +181,10 @@ private:
std::unique_ptr<PartitionerBase> _partitioner;
};
+/// Instantiated once in join_build_sink_operator.cpp; suppresses per-TU
implicit
+/// instantiation.
+extern template class
JoinBuildSinkOperatorX<PartitionedHashJoinSinkLocalState>;
+extern template class JoinBuildSinkLocalState<PartitionedHashJoinSharedState,
+
PartitionedHashJoinSinkLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/rec_cte_anchor_sink_operator.h
b/be/src/exec/operator/rec_cte_anchor_sink_operator.h
index 05e070ef470..5eb74d84073 100644
--- a/be/src/exec/operator/rec_cte_anchor_sink_operator.h
+++ b/be/src/exec/operator/rec_cte_anchor_sink_operator.h
@@ -121,4 +121,7 @@ private:
bool _need_notify_rec_side_ready = true;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class PipelineXSinkLocalState<RecCTESharedState>;
+
} // namespace doris
\ No newline at end of file
diff --git a/be/src/exec/operator/rec_cte_sink_operator.h
b/be/src/exec/operator/rec_cte_sink_operator.h
index cf5d36239f6..d7dda6ceca3 100644
--- a/be/src/exec/operator/rec_cte_sink_operator.h
+++ b/be/src/exec/operator/rec_cte_sink_operator.h
@@ -97,4 +97,7 @@ private:
VExprContextSPtrs _child_expr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class PipelineXSinkLocalState<RecCTESharedState>;
+
} // namespace doris
\ No newline at end of file
diff --git a/be/src/exec/operator/rec_cte_source_operator.h
b/be/src/exec/operator/rec_cte_source_operator.h
index 7f12f254922..f7f375151f8 100644
--- a/be/src/exec/operator/rec_cte_source_operator.h
+++ b/be/src/exec/operator/rec_cte_source_operator.h
@@ -324,4 +324,7 @@ private:
bool _is_used_by_other_rec_cte = false;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class PipelineXLocalState<RecCTESharedState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/repeat_operator.h
b/be/src/exec/operator/repeat_operator.h
index 43348d2fc5a..52f2c2fe201 100644
--- a/be/src/exec/operator/repeat_operator.h
+++ b/be/src/exec/operator/repeat_operator.h
@@ -90,4 +90,7 @@ private:
VExprContextSPtrs _expr_ctxs;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class StatefulOperatorX<RepeatLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/result_file_sink_operator.h
b/be/src/exec/operator/result_file_sink_operator.h
index 6151918df9b..f1dc61dae88 100644
--- a/be/src/exec/operator/result_file_sink_operator.h
+++ b/be/src/exec/operator/result_file_sink_operator.h
@@ -88,4 +88,7 @@ private:
std::shared_ptr<ResultBlockBufferBase> _sender = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VFileResultWriter,
ResultFileSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/select_operator.h
b/be/src/exec/operator/select_operator.h
index 9c4fa8af1bc..f5b10763a39 100644
--- a/be/src/exec/operator/select_operator.h
+++ b/be/src/exec/operator/select_operator.h
@@ -54,4 +54,7 @@ public:
[[nodiscard]] bool is_source() const override { return false; }
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class StreamingOperatorX<SelectLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/set_probe_sink_operator.h
b/be/src/exec/operator/set_probe_sink_operator.h
index acf28eb0fd7..e09eac84909 100644
--- a/be/src/exec/operator/set_probe_sink_operator.h
+++ b/be/src/exec/operator/set_probe_sink_operator.h
@@ -133,4 +133,11 @@ private:
using OperatorBase::_child;
};
+/// Instantiated once in set_probe_sink_operator.cpp; suppresses per-TU
implicit
+/// instantiation.
+extern template class SetProbeSinkLocalState<true>;
+extern template class SetProbeSinkLocalState<false>;
+extern template class SetProbeSinkOperatorX<true>;
+extern template class SetProbeSinkOperatorX<false>;
+
} // namespace doris
diff --git a/be/src/exec/operator/set_sink_operator.h
b/be/src/exec/operator/set_sink_operator.h
index a49e89b7b01..ff8b568c102 100644
--- a/be/src/exec/operator/set_sink_operator.h
+++ b/be/src/exec/operator/set_sink_operator.h
@@ -149,4 +149,10 @@ private:
const std::vector<TRuntimeFilterDesc> _runtime_filter_descs;
};
+/// Instantiated once in set_sink_operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class SetSinkLocalState<true>;
+extern template class SetSinkLocalState<false>;
+extern template class SetSinkOperatorX<true>;
+extern template class SetSinkOperatorX<false>;
+
} // namespace doris
diff --git a/be/src/exec/operator/set_source_operator.h
b/be/src/exec/operator/set_source_operator.h
index c502c0cb2e9..d8d73de4cca 100644
--- a/be/src/exec/operator/set_source_operator.h
+++ b/be/src/exec/operator/set_source_operator.h
@@ -103,4 +103,11 @@ private:
const size_t _child_quantity;
const bool _is_colocate;
};
+
+/// Instantiated once in set_source_operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class SetSourceLocalState<true>;
+extern template class SetSourceLocalState<false>;
+extern template class SetSourceOperatorX<true>;
+extern template class SetSourceOperatorX<false>;
+
} // namespace doris
diff --git a/be/src/exec/operator/spill_iceberg_table_sink_operator.h
b/be/src/exec/operator/spill_iceberg_table_sink_operator.h
index bd981531896..e05d0c48164 100644
--- a/be/src/exec/operator/spill_iceberg_table_sink_operator.h
+++ b/be/src/exec/operator/spill_iceberg_table_sink_operator.h
@@ -89,4 +89,7 @@ private:
ObjectPool* _pool = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VIcebergTableWriter,
SpillIcebergTableSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/operator/streaming_aggregation_operator.h
b/be/src/exec/operator/streaming_aggregation_operator.h
index 1c57d0ca33f..48fae130213 100644
--- a/be/src/exec/operator/streaming_aggregation_operator.h
+++ b/be/src/exec/operator/streaming_aggregation_operator.h
@@ -283,4 +283,7 @@ private:
std::vector<TExpr> _partition_exprs;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class StatefulOperatorX<StreamingAggLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/table_function_operator.h
b/be/src/exec/operator/table_function_operator.h
index de6e546af1d..de529986c38 100644
--- a/be/src/exec/operator/table_function_operator.h
+++ b/be/src/exec/operator/table_function_operator.h
@@ -182,4 +182,7 @@ private:
std::vector<int> _child_slot_sizes;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class StatefulOperatorX<TableFunctionLocalState>;
+
} // namespace doris
diff --git a/be/src/exec/operator/tvf_table_sink_operator.h
b/be/src/exec/operator/tvf_table_sink_operator.h
index e1a06e675c9..4f1954a2f27 100644
--- a/be/src/exec/operator/tvf_table_sink_operator.h
+++ b/be/src/exec/operator/tvf_table_sink_operator.h
@@ -82,4 +82,7 @@ private:
ObjectPool* _pool = nullptr;
};
+/// Instantiated once in operator.cpp; suppresses per-TU implicit
instantiation.
+extern template class AsyncWriterSink<VTVFTableWriter, TVFTableSinkOperatorX>;
+
} // namespace doris
diff --git a/be/src/exec/partitioner/partitioner.h
b/be/src/exec/partitioner/partitioner.h
index aa56bf1c80e..98607c36236 100644
--- a/be/src/exec/partitioner/partitioner.h
+++ b/be/src/exec/partitioner/partitioner.h
@@ -191,4 +191,9 @@ private:
}
};
+/// Instantiated once in partitioner.cpp; suppresses per-TU implicit
instantiation.
+extern template class Crc32HashPartitioner<ShuffleChannelIds>;
+extern template class Crc32HashPartitioner<SpillPartitionChannelIds>;
+extern template class Crc32HashPartitioner<SpillRePartitionChannelIds>;
+
} // namespace doris
diff --git a/be/src/exprs/table_function/vjson_each.h
b/be/src/exprs/table_function/vjson_each.h
index 2a9ddb64599..a779b76aa9d 100644
--- a/be/src/exprs/table_function/vjson_each.h
+++ b/be/src/exprs/table_function/vjson_each.h
@@ -69,4 +69,8 @@ private:
using VJsonEachTableFn = VJsonEachTableFunction<false>;
using VJsonEachTextTableFn = VJsonEachTableFunction<true>;
+/// Instantiated once in vjson_each.cpp; suppresses per-TU implicit
instantiation.
+extern template class VJsonEachTableFunction<false>;
+extern template class VJsonEachTableFunction<true>;
+
} // namespace doris
diff --git a/be/src/format/parquet/vparquet_column_chunk_reader.h
b/be/src/format/parquet/vparquet_column_chunk_reader.h
index 064d28fc115..a2805fe9379 100644
--- a/be/src/format/parquet/vparquet_column_chunk_reader.h
+++ b/be/src/format/parquet/vparquet_column_chunk_reader.h
@@ -286,4 +286,10 @@ private:
bool has_dict_page(const tparquet::ColumnMetaData& column);
+/// Instantiated once in vparquet_column_chunk_reader.cpp; suppresses per-TU
implicit instantiation.
+extern template class ColumnChunkReader<true, true>;
+extern template class ColumnChunkReader<true, false>;
+extern template class ColumnChunkReader<false, true>;
+extern template class ColumnChunkReader<false, false>;
+
} // namespace doris
diff --git a/be/src/format/parquet/vparquet_column_reader.h
b/be/src/format/parquet/vparquet_column_reader.h
index 7217c2b547d..acca51a28c5 100644
--- a/be/src/format/parquet/vparquet_column_reader.h
+++ b/be/src/format/parquet/vparquet_column_reader.h
@@ -546,4 +546,10 @@ public:
void reset_filter_map_index() override { _filter_map_index = 0; }
};
+/// Instantiated once in vparquet_column_reader.cpp; suppresses per-TU
implicit instantiation.
+extern template class ScalarColumnReader<true, true>;
+extern template class ScalarColumnReader<true, false>;
+extern template class ScalarColumnReader<false, true>;
+extern template class ScalarColumnReader<false, false>;
+
}; // namespace doris
diff --git a/be/src/format/parquet/vparquet_page_reader.h
b/be/src/format/parquet/vparquet_page_reader.h
index 37e3b480bba..785ff304812 100644
--- a/be/src/format/parquet/vparquet_page_reader.h
+++ b/be/src/format/parquet/vparquet_page_reader.h
@@ -258,4 +258,10 @@ std::unique_ptr<PageReader<IN_COLLECTION, OFFSET_INDEX>>
create_page_reader(
reader, io_ctx, offset, length, total_rows, metadata, ctx,
offset_index);
}
+/// Instantiated once in vparquet_page_reader.cpp; suppresses per-TU implicit
instantiation.
+extern template class PageReader<true, true>;
+extern template class PageReader<true, false>;
+extern template class PageReader<false, true>;
+extern template class PageReader<false, false>;
+
} // namespace doris
diff --git a/be/src/format_v2/parquet/reader/native/column_chunk_reader.h
b/be/src/format_v2/parquet/reader/native/column_chunk_reader.h
index a50b7e4bc08..e866e8b1c49 100644
--- a/be/src/format_v2/parquet/reader/native/column_chunk_reader.h
+++ b/be/src/format_v2/parquet/reader/native/column_chunk_reader.h
@@ -472,4 +472,10 @@ private:
bool has_dict_page(const tparquet::ColumnMetaData& column);
+/// Instantiated once in column_chunk_reader.cpp; suppresses per-TU implicit
instantiation.
+extern template class ColumnChunkReader<true, true>;
+extern template class ColumnChunkReader<true, false>;
+extern template class ColumnChunkReader<false, true>;
+extern template class ColumnChunkReader<false, false>;
+
} // namespace doris::format::parquet::native
diff --git a/be/src/format_v2/parquet/reader/native/column_reader.h
b/be/src/format_v2/parquet/reader/native/column_reader.h
index b43822cd165..01c6832ac0f 100644
--- a/be/src/format_v2/parquet/reader/native/column_reader.h
+++ b/be/src/format_v2/parquet/reader/native/column_reader.h
@@ -710,4 +710,10 @@ public:
void reset_filter_map_index() override { _filter_map_index = 0; }
};
+/// Instantiated once in column_reader.cpp; suppresses per-TU implicit
instantiation.
+extern template class ScalarColumnReader<true, true>;
+extern template class ScalarColumnReader<true, false>;
+extern template class ScalarColumnReader<false, true>;
+extern template class ScalarColumnReader<false, false>;
+
} // namespace doris::format::parquet::native
diff --git a/be/src/format_v2/parquet/reader/native/page_reader.h
b/be/src/format_v2/parquet/reader/native/page_reader.h
index da2c066891b..7686f2e5904 100644
--- a/be/src/format_v2/parquet/reader/native/page_reader.h
+++ b/be/src/format_v2/parquet/reader/native/page_reader.h
@@ -300,4 +300,10 @@ std::unique_ptr<PageReader<IN_COLLECTION, OFFSET_INDEX>>
create_page_reader(
reader, io_ctx, offset, length, total_rows, metadata, ctx,
offset_index);
}
+/// Instantiated once in page_reader.cpp; suppresses per-TU implicit
instantiation.
+extern template class PageReader<true, true>;
+extern template class PageReader<true, false>;
+extern template class PageReader<false, true>;
+extern template class PageReader<false, false>;
+
} // namespace doris::format::parquet::native
diff --git a/be/src/storage/cache/page_cache.h
b/be/src/storage/cache/page_cache.h
index 1cc98c5cb49..6f88ff1571d 100644
--- a/be/src/storage/cache/page_cache.h
+++ b/be/src/storage/cache/page_cache.h
@@ -277,4 +277,7 @@ private:
DISALLOW_COPY_AND_ASSIGN(PageCacheHandle);
};
+/// Instantiated once in page_cache.cpp; suppresses per-TU implicit
instantiation.
+extern template class
MemoryTrackedPageWithPagePtr<segment_v2::SegmentFooterPB>;
+
} // namespace doris
diff --git a/be/src/storage/index/inverted/inverted_index_writer.h
b/be/src/storage/index/inverted/inverted_index_writer.h
index 3ef7b4d9319..4c78e863497 100644
--- a/be/src/storage/index/inverted/inverted_index_writer.h
+++ b/be/src/storage/index/inverted/inverted_index_writer.h
@@ -29,14 +29,12 @@
#include "storage/index/inverted/util/reader.h"
#include "storage/olap_common.h"
#include "storage/segment/common.h"
+#include "storage/types.h"
namespace doris {
class KeyCoder;
-template <FieldType field_type>
-struct CppTypeTraits;
-
namespace segment_v2 {
using namespace doris::segment_v2::inverted_index;
@@ -104,5 +102,31 @@ private:
bool _should_analyzer = false;
};
+/// Instantiated once in inverted_index_writer.cpp; suppresses per-TU implicit
instantiation.
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_CHAR>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_VARCHAR>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_STRING>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_TINYINT>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_SMALLINT>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_INT>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_UNSIGNED_INT>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_BIGINT>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_LARGEINT>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DATE>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DATETIME>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DECIMAL>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DATEV2>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DATETIMEV2>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_TIMESTAMPTZ>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DECIMAL32>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DECIMAL64>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DECIMAL128I>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DECIMAL256>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_BOOL>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_IPV4>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_IPV6>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_FLOAT>;
+extern template class
InvertedIndexColumnWriter<FieldType::OLAP_FIELD_TYPE_DOUBLE>;
+
} // namespace segment_v2
} // namespace doris
\ No newline at end of file
diff --git
a/be/src/storage/index/inverted/query_v2/boolean_query/occur_boolean_weight.h
b/be/src/storage/index/inverted/query_v2/boolean_query/occur_boolean_weight.h
index d3157c81473..a0f9a56809c 100644
---
a/be/src/storage/index/inverted/query_v2/boolean_query/occur_boolean_weight.h
+++
b/be/src/storage/index/inverted/query_v2/boolean_query/occur_boolean_weight.h
@@ -20,6 +20,7 @@
#include <roaring/roaring.hh>
#include "storage/index/inverted/query_v2/boolean_query/occur.h"
+#include "storage/index/inverted/query_v2/score_combiner.h"
#include "storage/index/inverted/query_v2/scorer.h"
#include "storage/index/inverted/query_v2/term_query/term_scorer.h"
#include "storage/index/inverted/query_v2/wand/block_wand.h"
@@ -140,4 +141,8 @@ void
OccurBooleanWeight<ScoreCombinerPtrT>::for_each_pruning(const QueryExecutio
std::move(specialized));
}
+/// Instantiated once in occur_boolean_weight.cpp; suppresses per-TU implicit
instantiation.
+extern template class OccurBooleanWeight<SumCombinerPtr>;
+extern template class OccurBooleanWeight<DoNothingCombinerPtr>;
+
} // namespace doris::segment_v2::inverted_index::query_v2
\ No newline at end of file
diff --git a/be/src/storage/index/inverted/query_v2/disjunction_scorer.h
b/be/src/storage/index/inverted/query_v2/disjunction_scorer.h
index 583c17bf3d6..90dc7de0fb4 100644
--- a/be/src/storage/index/inverted/query_v2/disjunction_scorer.h
+++ b/be/src/storage/index/inverted/query_v2/disjunction_scorer.h
@@ -20,6 +20,7 @@
#include <queue>
#include <vector>
+#include "storage/index/inverted/query_v2/score_combiner.h"
#include "storage/index/inverted/query_v2/scorer.h"
namespace doris::segment_v2::inverted_index::query_v2 {
@@ -63,4 +64,8 @@ template <typename ScoreCombinerPtrT>
ScorerPtr make_disjunction(std::vector<ScorerPtr> scorers, ScoreCombinerPtrT
score_combiner,
size_t minimum_matches_required);
+/// Instantiated once in disjunction_scorer.cpp; suppresses per-TU implicit
instantiation.
+extern template class DisjunctionScorer<SumCombinerPtr>;
+extern template class DisjunctionScorer<DoNothingCombinerPtr>;
+
} // namespace doris::segment_v2::inverted_index::query_v2
\ No newline at end of file
diff --git a/be/src/storage/index/inverted/query_v2/exclude_scorer.h
b/be/src/storage/index/inverted/query_v2/exclude_scorer.h
index e7679d60bfd..0a1ed6ac8ac 100644
--- a/be/src/storage/index/inverted/query_v2/exclude_scorer.h
+++ b/be/src/storage/index/inverted/query_v2/exclude_scorer.h
@@ -57,4 +57,7 @@ ScorerPtr make_exclude(ScorerPtr underlying, ScorerPtr
excluding,
roaring::Roaring exclude_null = {},
const NullBitmapResolver* resolver = nullptr);
+/// Instantiated once in exclude_scorer.cpp; suppresses per-TU implicit
instantiation.
+extern template class Exclude<ScorerPtr, ScorerPtr>;
+
} // namespace doris::segment_v2::inverted_index::query_v2
diff --git
a/be/src/storage/index/inverted/query_v2/phrase_query/phrase_scorer.h
b/be/src/storage/index/inverted/query_v2/phrase_query/phrase_scorer.h
index b86067bd4b1..072b921f199 100644
--- a/be/src/storage/index/inverted/query_v2/phrase_query/phrase_scorer.h
+++ b/be/src/storage/index/inverted/query_v2/phrase_query/phrase_scorer.h
@@ -113,4 +113,8 @@ inline void
PhraseScorer<TPostings>::intersection(std::vector<uint32_t>& left,
left.resize(count);
}
+/// Instantiated once in phrase_scorer.cpp; suppresses per-TU implicit
instantiation.
+extern template class PhraseScorer<PostingsPtr>;
+extern template class PhraseScorer<SegmentPostingsPtr>;
+
} // namespace doris::segment_v2::inverted_index::query_v2
\ No newline at end of file
diff --git a/be/src/storage/index/inverted/query_v2/union/simple_union.h
b/be/src/storage/index/inverted/query_v2/union/simple_union.h
index d06a4b5ac31..dcc9506d181 100644
--- a/be/src/storage/index/inverted/query_v2/union/simple_union.h
+++ b/be/src/storage/index/inverted/query_v2/union/simple_union.h
@@ -62,4 +62,9 @@ auto make_simple_union(std::vector<TDocSet> docsets) {
return SimpleUnion<TDocSet>::create(std::move(docsets));
}
+/// Instantiated once in simple_union.cpp; suppresses per-TU implicit
instantiation.
+extern template class SimpleUnion<MockDocSetPtr>;
+extern template class SimpleUnion<PostingsPtr>;
+extern template class SimpleUnion<SegmentPostingsPtr>;
+
} // namespace doris::segment_v2::inverted_index::query_v2
\ No newline at end of file
diff --git a/be/src/util/frame_of_reference_coding.h
b/be/src/util/frame_of_reference_coding.h
index f3557bc6985..55d8143f271 100644
--- a/be/src/util/frame_of_reference_coding.h
+++ b/be/src/util/frame_of_reference_coding.h
@@ -210,4 +210,32 @@ private:
uint32_t _current_decoded_frame = -1;
std::vector<T> _out_buffer; // store values of decoded frame
};
+
+template <>
+const uint24_t ForEncoder<uint24_t>::numeric_limits_max();
+
+/// Instantiated once in frame_of_reference_coding.cpp; suppresses per-TU
implicit instantiation.
+extern template class ForEncoder<int8_t>;
+extern template class ForEncoder<int16_t>;
+extern template class ForEncoder<int32_t>;
+extern template class ForEncoder<int64_t>;
+extern template class ForEncoder<int128_t>;
+extern template class ForEncoder<uint8_t>;
+extern template class ForEncoder<uint16_t>;
+extern template class ForEncoder<uint32_t>;
+extern template class ForEncoder<uint64_t>;
+extern template class ForEncoder<uint24_t>;
+extern template class ForEncoder<uint128_t>;
+extern template class ForDecoder<int8_t>;
+extern template class ForDecoder<int16_t>;
+extern template class ForDecoder<int32_t>;
+extern template class ForDecoder<int64_t>;
+extern template class ForDecoder<int128_t>;
+extern template class ForDecoder<uint8_t>;
+extern template class ForDecoder<uint16_t>;
+extern template class ForDecoder<uint32_t>;
+extern template class ForDecoder<uint64_t>;
+extern template class ForDecoder<uint24_t>;
+extern template class ForDecoder<uint128_t>;
+
} // namespace doris
diff --git a/be/src/util/json/json_parser.h b/be/src/util/json/json_parser.h
index c4a165e8995..ee91765d44d 100644
--- a/be/src/util/json/json_parser.h
+++ b/be/src/util/json/json_parser.h
@@ -172,4 +172,8 @@ private:
ParserImpl parser;
};
+class SimdJSONParser;
+/// Instantiated once in json_parser.cpp; suppresses per-TU implicit
instantiation.
+extern template class JSONDataParser<SimdJSONParser>;
+
} // namespace doris
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]