github-actions[bot] commented on code in PR #67983:
URL: https://github.com/apache/doris/pull/67983#discussion_r4043280447


##########
be/src/storage/segment/variant/v2/variant_path_builder.cpp:
##########
@@ -219,8 +219,16 @@ const DataTypePtr& cached_decimal_type(uint32_t scale) {
     return types[scale];
 }
 
-DataTypePtr infer_type(VariantRef value, const DataTypePtr& reusable_type = 
nullptr) {
-    const ValueKind kind = value_kind(value);
+const DataTypePtr& array_element_type(const DataTypeArray& array) {
+    // DataTypeArray always wraps its element in Nullable. Borrow the element 
instead of copying it
+    // through remove_nullable(): element types are process-wide statics 
shared by concurrent
+    // flushes, so each shared_ptr copy is a contended reference-count update.
+    return assert_cast<const 
DataTypeNullable&>(*array.get_nested_type()).get_nested_type();
+}
+
+// Every scalar storage type is a process-wide static, so it is returned by 
reference.
+const DataTypePtr& infer_scalar_type(VariantRef value, ValueKind kind) {
+    DORIS_CHECK(kind != ValueKind::ARRAY);

Review Comment:
   [P2] Use a debug-only check for this established hot-path invariant
   
   `infer_scalar_type()` is called once per scalar array element, while both 
callers already establish `kind != ARRAY` (the top-level branch checks it and 
the array loop returns before this call for nested arrays). `DORIS_CHECK` has 
release semantics, even though inlining may let a particular optimized build 
prove and remove it, and the repository guidance explicitly requires `DCHECK` 
for invariants in performance-sensitive loops. Please use `DCHECK` here (or 
remove the redundant check) so release behavior does not depend on the 
optimizer eliminating a check from the exact loop this PR targets.



##########
be/test/storage/variant/variant_column_writer_reader_test.cpp:
##########
@@ -758,6 +759,69 @@ TEST(VariantPathBuilderTest, 
PreservesIncomingArrayWhenInferredDecimalPromotionO
               "[9999999999999999999999999999999999999.9]");
 }
 
+TEST(VariantPathBuilderTest, ArrayPathReusesElementTypeAcrossRows) {
+    VariantBatchBuilder value_builder;
+    const auto append_array = [&](auto&& fill) {
+        auto row = value_builder.begin_row();
+        auto array = row.start_array();
+        fill(row);
+        array.finish();
+        row.finish();
+    };
+    append_array([](auto& row) {
+        row.add_float(1.0F);
+        row.add_float(2.0F);
+    });
+    append_array([](auto& row) {
+        row.add_float(3.0F);
+        row.add_null();
+    });
+    append_array([](auto& row) { row.add_null(); });
+    append_array([](auto& row) { row.add_double(4.5); });
+    append_array([](auto& row) { row.add_float(5.0F); });
+    VariantBatchBuilder values = value_builder.finish_batch();
+
+    const auto element_primitive = [](const DataTypePtr& type) {
+        const DataTypePtr array = remove_nullable(type);
+        return remove_nullable(assert_cast<const 
DataTypeArray&>(*array).get_nested_type())
+                ->get_primitive_type();
+    };
+    segment_v2::VariantPathBuilder builder(PathInData("metric"));
+    // FLOAT arrays, arrays with null elements, and all-null arrays share the 
first row's type.
+    for (size_t row = 0; row < 3; ++row) {
+        ASSERT_TRUE(builder.append(values.value_at(row), row).ok());
+        EXPECT_EQ(builder.promotion_count(), 0) << "row=" << row;

Review Comment:
   [P2] Make this test observe the optimized path
   
   `promotion_count()` only changes when `Impl::promote()` rewrites the stored 
column. On the base code, same-type FLOAT arrays already returned 
`reusable_type` after paying `path_least_common_type(Nullable(FLOAT), FLOAT)`, 
so these rows still reported zero promotions; the DOUBLE row caused the same 
one promotion, and every type/value/null assertion below was identical. The 
per-element static `shared_ptr` copies are also invisible here. As a result, 
this test stays green if both performance fixes are reverted. Please add a 
deterministic BE_TEST counter/hook (or equivalent oracle) for the avoided 
common-type/owning-copy path that fails on the base implementation, while 
keeping these semantic assertions.



##########
be/src/storage/segment/variant/v2/variant_path_builder.cpp:
##########
@@ -219,8 +219,16 @@ const DataTypePtr& cached_decimal_type(uint32_t scale) {
     return types[scale];
 }
 
-DataTypePtr infer_type(VariantRef value, const DataTypePtr& reusable_type = 
nullptr) {
-    const ValueKind kind = value_kind(value);
+const DataTypePtr& array_element_type(const DataTypeArray& array) {
+    // DataTypeArray always wraps its element in Nullable. Borrow the element 
instead of copying it
+    // through remove_nullable(): element types are process-wide statics 
shared by concurrent
+    // flushes, so each shared_ptr copy is a contended reference-count update.
+    return assert_cast<const 
DataTypeNullable&>(*array.get_nested_type()).get_nested_type();

Review Comment:
   [P2] Use the typed accessor instead of release RTTI here
   
   The default `assert_cast` has release `typeid`/failure semantics, and this 
helper is reached from reusable inference, representability, and append for 
repeated array values. `DataTypeArray` is `final`; its constructor already 
validates and stores the wrapper as `DataTypeNullablePtr`, and 
`get_nullable_nested_type()` exposes that owner directly. Please return 
`array.get_nullable_nested_type()->get_nested_type()` so this borrow keeps the 
same lifetime guarantee without making removal of redundant RTTI on the hot 
path optimizer-dependent.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to