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

yiguolei pushed a commit to branch branch-4.2
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.2 by this push:
     new 11f7e8485dd branch-4.2: [improvement](be) Run-optimize the SNII NULL 
bitmap before serializing it #69727 (#69789)
11f7e8485dd is described below

commit 11f7e8485ddf1e85d3e75715757f99f56ee79d3e
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Oct 29 17:20:07 2026 +0800

    branch-4.2: [improvement](be) Run-optimize the SNII NULL bitmap before 
serializing it #69727 (#69789)
    
    Cherry-picked from #69727
    
    Co-authored-by: Jack <[email protected]>
---
 .../index/inverted/snii/format/null_bitmap.cpp     |  6 +++++
 .../inverted/snii/format/null_bitmap_test.cpp      | 31 ++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/be/src/storage/index/inverted/snii/format/null_bitmap.cpp 
b/be/src/storage/index/inverted/snii/format/null_bitmap.cpp
index 12d35c8b4e4..78eb5c55a6d 100644
--- a/be/src/storage/index/inverted/snii/format/null_bitmap.cpp
+++ b/be/src/storage/index/inverted/snii/format/null_bitmap.cpp
@@ -182,6 +182,12 @@ Status NullBitmapWriter::serialization_sizes(uint32_t 
doc_count,
         return Status::Error<ErrorCode::INVALID_ARGUMENT, false>(
                 "null bitmap: null serialization size output");
     }
+    // Rewrites the containers into their smallest form, as the V2 writer does 
before it serializes.
+    // Runs of NULL rows (a path that is absent from most rows of a sparse 
column) are the common
+    // case, and as plain array or bitset containers they cost about 8 KiB per 
65536 rows instead
+    // of a few bytes. This is the one place that fixes the serialized size, 
and finish() sizes
+    // itself through here, so the sizes reported to callers and the bytes 
written always agree.
+    bitmap_->runOptimize();
     const size_t roaring_bytes = bitmap_->getSizeInBytes();
     const size_t prefix_bytes = varint_len(doc_count) + 
varint_len(roaring_bytes);
     if (roaring_bytes > std::numeric_limits<size_t>::max() - prefix_bytes) {
diff --git a/be/test/storage/index/inverted/snii/format/null_bitmap_test.cpp 
b/be/test/storage/index/inverted/snii/format/null_bitmap_test.cpp
index 9cea5338ee1..6ad1bd78f34 100644
--- a/be/test/storage/index/inverted/snii/format/null_bitmap_test.cpp
+++ b/be/test/storage/index/inverted/snii/format/null_bitmap_test.cpp
@@ -22,6 +22,7 @@
 #include <algorithm>
 #include <cstdint>
 #include <limits>
+#include <numeric>
 #include <span>
 #include <string>
 #include <vector>
@@ -80,6 +81,36 @@ TEST(SniiNullBitmap, RoundTripPerDoc) {
     }
 }
 
+// A long run of NULL rows -- the usual shape of a path that is absent from 
most rows of a sparse
+// column -- must be written as run containers: a few bytes per 65536 rows 
instead of 8 KiB of
+// bitset. The size reported ahead of the write must be the size written.
+TEST(SniiNullBitmap, RunsOfNullsSerializeAsRuns) {
+    constexpr uint32_t kRows = 1'000'000;
+    std::vector<uint32_t> nulls(kRows);
+    std::iota(nulls.begin(), nulls.end(), 0U);
+    NullBitmapWriter writer;
+    writer.add_many(nulls);
+
+    doris::snii::format::NullBitmapSerializationSizes sizes;
+    ASSERT_TRUE(writer.serialization_sizes(kRows, &sizes).ok());
+    // 16 containers of one run each; as bitsets they would take 16 * 8 KiB.
+    EXPECT_LT(sizes.roaring_bytes, 256U);
+
+    ByteSink sink;
+    ASSERT_TRUE(writer.finish(kRows, &sink).ok());
+    EXPECT_EQ(sink.size(), sizes.framed_bytes);
+
+    NullBitmapReader reader;
+    ASSERT_TRUE(NullBitmapReader::open(sink.view(), &reader).ok());
+    EXPECT_EQ(reader.null_count(), kRows);
+    EXPECT_TRUE(reader.is_null(0));
+    EXPECT_TRUE(reader.is_null(kRows - 1));
+    EXPECT_FALSE(reader.is_null(kRows));
+    uint64_t decoded_bytes = 0;
+    ASSERT_TRUE(NullBitmapReader::decoded_memory_bytes(sink.view(), 
&decoded_bytes).ok());
+    EXPECT_GT(decoded_bytes, 0U);
+}
+
 // Writer null_count reflects the number of distinct null docids added.
 TEST(SniiNullBitmap, WriterNullCount) {
     NullBitmapWriter writer;


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

Reply via email to