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

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


The following commit(s) were added to refs/heads/master by this push:
     new 03750ab553d9 [SPARK-56892][SQL] Bulk read optimization for Parquet 
DELTA_BINARY_PACKED decoding
03750ab553d9 is described below

commit 03750ab553d9ebf446e61e077e867d45436f72b0
Author: Ismaël Mejía <[email protected]>
AuthorDate: Tue Jun 16 10:48:23 2026 +0800

    [SPARK-56892][SQL] Bulk read optimization for Parquet DELTA_BINARY_PACKED 
decoding
    
    ### What changes were proposed in this pull request?
    
    Replace per-element lambda dispatch in `readIntegers`/`readLongs` with bulk 
paths that compute prefix sums in-place over the unpacked delta buffer and 
write via `putInts`/`putLongs` (backed by `System.arraycopy` on-heap).
    
    Three optimizations in this PR:
    
    1. **Bulk read for INT32/INT64**: `readBulkIntegers` and `readBulkLongs` 
replace the generic `readValues()` lambda-per-value path. A single 
`loadMiniBlockBulk` method handles block/mini-block loading, prefix-sum 
computation, and delegates the type-specific write to a `BulkWriter` callback 
(called once per mini-block, not per value).
    
    2. **Zero-allocation unsigned long encoding**: Replace `new 
BigInteger(Long.toUnsignedString(v)).toByteArray()` (3 allocations per value: 
String + BigInteger + byte[]) with a loop-based `byte[]` encoder using 
`Long.numberOfLeadingZeros` to compute minimal BigInteger-compatible encoding 
directly. The shared utility `encodeUnsignedLongBigEndian` is extracted into 
`VectorizedReaderBase` and applied to all call sites 
(`VectorizedDeltaBinaryPackedReader`, `UnsignedLongUpdater`, `ParquetDic [...]
    
    3. **Widening overrides** (`readIntegersAsLongs`, `readIntegersAsDoubles`): 
Since the delta decoder already works on `long[]` internally, these overrides 
skip the int narrowing step and write longs/doubles directly from the 
prefix-sum buffer. Benefits `DateToTimestampNTZUpdater`, 
`IntegerToLongUpdater`, and `IntegerToDoubleUpdater` via the two-pass updater 
pattern.
    
    4. **Benchmark fix**: Add `unsignedLongVec.reset()` before 
`readUnsignedLongs` to prevent unbounded `arrayData()` growth across benchmark 
iterations (OOM).
    
    ### Why are the changes needed?
    
    The DELTA_BINARY_PACKED decoder was 2-5x slower than PLAIN encoding for 
INT32/INT64 reads due to per-element lambda dispatch and lack of bulk vector 
writes. The `readUnsignedLongs` path allocated 3 objects per value (12,288 
allocations per 4096-row batch) due to `BigInteger(Long.toUnsignedString(v))`.
    
    #### Benchmark Results (AMD EPYC 7763, JDK 17/21/25)
    
    Results from GHA benchmark workflow runs committed to this branch. Both 
baseline (upstream master) and this PR ran on AMD EPYC 7763 64-Core Processor.
    
    **DELTA_BINARY_PACKED INT64** (primary optimization target):
    
    | Case | JDK 17 Baseline | JDK 17 PR | Speedup | JDK 21 Baseline | JDK 21 
PR | Speedup | JDK 25 Baseline | JDK 25 PR | Speedup |
    |---|---|---|---|---|---|---|---|---|---|
    | readLongs, constant | 191.0 | 535.8 | **2.8x** | 195.2 | 477.9 | **2.4x** 
| 163.0 | 508.3 | **3.1x** |
    | readLongs, monotonic | 144.9 | 534.1 | **3.7x** | 158.8 | 478.2 | 
**3.0x** | 139.1 | 520.9 | **3.7x** |
    | readLongs, small-delta random | 134.8 | 368.4 | **2.7x** | 139.4 | 334.4 
| **2.4x** | 122.7 | 356.6 | **2.9x** |
    | readLongs, wide random | 97.8 | 187.7 | **1.9x** | 102.9 | 182.3 | 
**1.8x** | 94.4 | 189.4 | **2.0x** |
    | skipLongs, constant | 170.1 | 612.6 | **3.6x** | 175.4 | 520.5 | **3.0x** 
| 152.1 | 603.1 | **4.0x** |
    | skipLongs, monotonic | 170.1 | 611.2 | **3.6x** | 175.6 | 526.5 | 
**3.0x** | 152.0 | 603.7 | **4.0x** |
    | skipLongs, small-delta random | 152.8 | 427.1 | **2.8x** | 152.5 | 356.2 
| **2.3x** | 133.9 | 397.2 | **3.0x** |
    
    **DELTA_BINARY_PACKED INT32:**
    
    | Case | JDK 17 Baseline | JDK 17 PR | Speedup | JDK 21 Baseline | JDK 21 
PR | Speedup | JDK 25 Baseline | JDK 25 PR | Speedup |
    |---|---|---|---|---|---|---|---|---|---|
    | readIntegers, constant | 482.3 | 375.1 | 0.78x | 451.8 | 482.9 | 1.07x | 
487.1 | 476.4 | 0.98x |
    | readIntegers, monotonic | 314.9 | 375.1 | **1.19x** | 369.7 | 478.9 | 
**1.30x** | 303.1 | 476.4 | **1.57x** |
    | readIntegers, small-delta random | 257.5 | 297.3 | **1.15x** | 308.6 | 
333.9 | 1.08x | 241.3 | 333.6 | **1.38x** |
    | readIntegers, wide random | 209.3 | 240.8 | **1.15x** | 249.2 | 270.9 | 
1.09x | 201.4 | 267.5 | **1.33x** |
    | skipIntegers, constant | 335.4 | 608.9 | **1.82x** | 415.1 | 519.8 | 
**1.25x** | 364.8 | 606.4 | **1.66x** |
    | skipIntegers, monotonic | 335.1 | 612.2 | **1.83x** | 415.6 | 529.0 | 
**1.27x** | 365.3 | 603.8 | **1.65x** |
    
    **DELTA_BYTE_ARRAY** (indirect benefit from INT64 bulk path):
    
    | Case | JDK 17 Baseline | JDK 17 PR | Speedup | JDK 21 Baseline | JDK 21 
PR | Speedup | JDK 25 Baseline | JDK 25 PR | Speedup |
    |---|---|---|---|---|---|---|---|---|---|
    | readBinary, no overlap, len=16 | 29.2 | 38.5 | **1.32x** | 29.6 | 38.7 | 
**1.31x** | 28.2 | 38.5 | **1.37x** |
    | readBinary, half overlap, len=16 | 25.0 | 31.0 | **1.24x** | 25.4 | 31.2 
| **1.23x** | 24.3 | 31.7 | **1.30x** |
    | readBinary, full overlap, len=16 | 24.8 | 30.2 | **1.22x** | 25.1 | 30.9 
| **1.23x** | 24.0 | 31.3 | **1.30x** |
    
    **DELTA_LENGTH_BYTE_ARRAY:**
    
    | Case | JDK 17 Baseline | JDK 17 PR | Speedup | JDK 21 Baseline | JDK 21 
PR | Speedup | JDK 25 Baseline | JDK 25 PR | Speedup |
    |---|---|---|---|---|---|---|---|---|---|
    | readBinary, payloadLen=8 | 48.1 | 63.3 | **1.32x** | 51.7 | 65.7 | 
**1.27x** | 48.7 | 63.8 | **1.31x** |
    | skipBinary, payloadLen=8 | 95.8 | 174.7 | **1.82x** | 106.3 | 182.0 | 
**1.71x** | 97.0 | 183.2 | **1.89x** |
    
    **Variant reads (unsigned long encoding + widening overrides):**
    
    | Case | JDK 17 Baseline | JDK 17 PR | Speedup | JDK 21 Baseline | JDK 21 
PR | Speedup | JDK 25 Baseline | JDK 25 PR | Speedup |
    |---|---|---|---|---|---|---|---|---|---|
    | readIntegersAsLongs (INT32 -> Long) | 121.4 | 291.1 | **2.4x** | 117.6 | 
286.8 | **2.4x** | 105.8 | 283.9 | **2.7x** |
    | readIntegersAsDoubles (INT32 -> Double) | 121.4 | 258.8 | **2.1x** | 
117.6 | 258.1 | **2.2x** | 105.8 | 253.0 | **2.4x** |
    | readUnsignedLongs (INT64 -> Decimal(20,0)) | 4.6 | 37.6 | **8.2x** | 4.5 
| 36.9 | **8.2x** | 5.0 | 36.8 | **7.4x** |
    
    > Note: Baseline for `readIntegersAsLongs`/`readIntegersAsDoubles` is 
`readUnsignedIntegers` which uses the per-row default `readInteger()` virtual 
dispatch path (same cost as the default widening methods without overrides).
    
    > Note: These results are from independent GHA runs (not back-to-back on 
the same runner). Some cross-run variance is present in unchanged paths. The 
INT64 bulk-read improvement (1.8x-3.7x), widening overrides (2.1x-2.7x), and 
the unsigned long encoding fix (7-9x) are the primary contributions of this PR.
    
    Full committed results: [JDK 
17](https://github.com/iemejia/spark/actions/runs/27426991381), [JDK 
21](https://github.com/iemejia/spark/actions/runs/27426992516), [JDK 
25](https://github.com/iemejia/spark/actions/runs/27431820511)
    
    ### Does this PR introduce _any_ user-facing change?
    
    No. This is a performance improvement to internal Parquet decoding. No API 
or behavior changes.
    
    ### How was this patch tested?
    
    - Existing unit tests: `ParquetDeltaEncodingInteger` (13 tests), 
`ParquetDeltaEncodingLong` (13 tests), `ParquetDeltaByteArrayEncodingSuite`, 
`ParquetDeltaLengthByteArrayEncodingSuite`, `ParquetVectorizedSuite` (25 
tests), `ParquetIOSuite` (unsigned Parquet logical types test) -- all pass.
    - Benchmark: `VectorizedDeltaReaderBenchmark` run via GHA workflow on JDK 
17, 21, and 25.
    
    ### Was this patch authored or co-authored using generative AI tooling?
    
    Generated-by: OpenCode (Claude claude-opus-4.6)
    
    Closes #55919 from iemejia/SPARK-56892-delta-binary-packed-bulk-read.
    
    Authored-by: Ismaël Mejía <[email protected]>
    Signed-off-by: yangjie01 <[email protected]>
---
 ...ectorizedDeltaReaderBenchmark-jdk21-results.txt |  98 ++++++-------
 ...ectorizedDeltaReaderBenchmark-jdk25-results.txt |  98 ++++++-------
 .../VectorizedDeltaReaderBenchmark-results.txt     |  98 ++++++-------
 .../datasources/parquet/ParquetDictionary.java     |   4 +-
 .../parquet/ParquetVectorUpdaterFactory.java       |  11 +-
 .../parquet/VectorizedDeltaBinaryPackedReader.java | 151 ++++++++++++++++++++-
 .../datasources/parquet/VectorizedReaderBase.java  |  38 ++++++
 .../parquet/VectorizedDeltaReaderBenchmark.scala   |  10 +-
 8 files changed, 351 insertions(+), 157 deletions(-)

diff --git 
a/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-jdk21-results.txt 
b/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-jdk21-results.txt
index a7199750be60..9f0397dd4d8b 100644
--- a/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-jdk21-results.txt
+++ b/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-jdk21-results.txt
@@ -2,92 +2,94 @@
 DELTA_BINARY_PACKED INT32
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_BINARY_PACKED INT32:                Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readIntegers, constant                                2              2         
  0        451.8           2.2       1.0X
-skipIntegers, constant                                3              3         
  0        415.1           2.4       0.9X
-readIntegers, monotonic                               3              3         
  0        369.7           2.7       0.8X
-skipIntegers, monotonic                               3              3         
  0        415.6           2.4       0.9X
-readIntegers, small-delta random                      3              3         
  0        308.6           3.2       0.7X
-skipIntegers, small-delta random                      3              3         
  0        358.6           2.8       0.8X
-readIntegers, wide random                             4              4         
  0        249.2           4.0       0.6X
-skipIntegers, wide random                             4              4         
  0        281.4           3.6       0.6X
+readIntegers, constant                                2              2         
  0        476.2           2.1       1.0X
+skipIntegers, constant                                2              2         
  0        561.5           1.8       1.2X
+readIntegers, monotonic                               2              2         
  0        480.9           2.1       1.0X
+skipIntegers, monotonic                               2              2         
  0        562.4           1.8       1.2X
+readIntegers, small-delta random                      3              3         
  0        330.9           3.0       0.7X
+skipIntegers, small-delta random                      3              3         
  0        376.2           2.7       0.8X
+readIntegers, wide random                             4              4         
  0        268.4           3.7       0.6X
+skipIntegers, wide random                             4              4         
  0        293.1           3.4       0.6X
 
 
 
================================================================================================
 DELTA_BINARY_PACKED INT64
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_BINARY_PACKED INT64:                Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readLongs, constant                                   5              6         
  0        195.2           5.1       1.0X
-skipLongs, constant                                   6              6         
  0        175.4           5.7       0.9X
-readLongs, monotonic                                  7              7         
  0        158.8           6.3       0.8X
-skipLongs, monotonic                                  6              6         
  0        175.6           5.7       0.9X
-readLongs, small-delta random                         8              8         
  0        139.4           7.2       0.7X
-skipLongs, small-delta random                         7              7         
  0        152.5           6.6       0.8X
-readLongs, wide random                               10             10         
  1        102.9           9.7       0.5X
-skipLongs, wide random                                6              9         
  2        185.5           5.4       1.0X
+readLongs, constant                                   2              2         
  0        518.5           1.9       1.0X
+skipLongs, constant                                   2              2         
  0        545.8           1.8       1.1X
+readLongs, monotonic                                  2              2         
  0        517.6           1.9       1.0X
+skipLongs, monotonic                                  2              2         
  0        559.7           1.8       1.1X
+readLongs, small-delta random                         3              3         
  0        357.3           2.8       0.7X
+skipLongs, small-delta random                         3              3         
  0        377.0           2.7       0.7X
+readLongs, wide random                                6              6         
  0        186.1           5.4       0.4X
+skipLongs, wide random                                5              6         
  0        190.7           5.2       0.4X
 
 
 
================================================================================================
 DELTA_BYTE_ARRAY
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_BYTE_ARRAY:                         Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readBinary, no overlap, len=16                       35             41         
  4         29.6          33.8       1.0X
-skipBinary, no overlap, len=16                       41             45         
  3         25.9          38.6       0.9X
-readBinary, half overlap, len=16                     41             44         
  3         25.4          39.3       0.9X
-skipBinary, half overlap, len=16                     47             50         
  5         22.3          44.8       0.8X
-readBinary, full overlap, len=16                     42             44         
  3         25.1          39.9       0.8X
-skipBinary, full overlap, len=16                     48             50         
  3         22.0          45.6       0.7X
-readBinary, half overlap, len=64                     42             42         
  1         25.2          39.6       0.9X
-skipBinary, half overlap, len=64                     47             50         
 14         22.4          44.6       0.8X
+readBinary, no overlap, len=16                       27             32         
  2         38.2          26.2       1.0X
+skipBinary, no overlap, len=16                       34             36         
  2         30.8          32.5       0.8X
+readBinary, half overlap, len=16                     33             34         
  0         31.5          31.7       0.8X
+skipBinary, half overlap, len=16                     38             39         
  1         27.7          36.1       0.7X
+readBinary, full overlap, len=16                     33             34         
  1         31.5          31.7       0.8X
+skipBinary, full overlap, len=16                     38             39         
  2         27.4          36.5       0.7X
+readBinary, half overlap, len=64                     33             34         
  1         31.6          31.7       0.8X
+skipBinary, half overlap, len=64                     38             39         
  2         27.9          35.8       0.7X
 
 
 
================================================================================================
 DELTA_LENGTH_BYTE_ARRAY
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_LENGTH_BYTE_ARRAY:                  Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readBinary, payloadLen=8                             20             21         
  0         51.7          19.3       1.0X
-skipBinary, payloadLen=8                             10             10         
  0        106.3           9.4       2.1X
-readBinary, payloadLen=32                            16             18         
  2         63.9          15.7       1.2X
-skipBinary, payloadLen=32                             6              6         
  0        175.9           5.7       3.4X
-readBinary, payloadLen=128                           19             19         
  0         56.0          17.8       1.1X
-skipBinary, payloadLen=128                            6              6         
  0        176.3           5.7       3.4X
-readBinary, payloadLen=512                           41             43         
  3         25.6          39.0       0.5X
-skipBinary, payloadLen=512                            6              6         
  1        176.4           5.7       3.4X
+readBinary, payloadLen=8                             16             16         
  0         65.7          15.2       1.0X
+skipBinary, payloadLen=8                              6              6         
  0        184.2           5.4       2.8X
+readBinary, payloadLen=32                            16             16         
  1         65.0          15.4       1.0X
+skipBinary, payloadLen=32                             6              6         
  0        185.6           5.4       2.8X
+readBinary, payloadLen=128                           18             19         
  1         56.9          17.6       0.9X
+skipBinary, payloadLen=128                            6              6         
  0        185.6           5.4       2.8X
+readBinary, payloadLen=512                           39             40         
  1         27.1          36.9       0.4X
+skipBinary, payloadLen=512                            6              6         
  0        185.5           5.4       2.8X
 
 
 
================================================================================================
 Variant reads
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 21.0.11+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 Variant reads:                                   Best Time(ms)   Avg Time(ms)  
 Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
-------------------------------------------------------------------------------------------------------------------------------
-readBytes (INT32)                                            7              7  
         0        142.3           7.0       1.0X
-readShorts (INT32)                                           7              8  
         0        143.0           7.0       1.0X
-readUnsignedIntegers (INT32 -> Long)                         7              7  
         0        147.1           6.8       1.0X
-readUnsignedLongs (INT64 -> Decimal(20,0))                 232            243  
        23          4.5         221.5       0.0X
-skipBytes                                                    4              4  
         0        285.4           3.5       2.0X
-skipShorts                                                   4              4  
         0        285.4           3.5       2.0X
-readByte (INT32 single-value)                               13             13  
         1         80.2          12.5       0.6X
-readShort (INT32 single-value)                              13             13  
         1         82.0          12.2       0.6X
-readInteger (INT32 single-value)                            13             13  
         0         80.2          12.5       0.6X
-readLong (INT64 single-value)                               14             14  
         0         74.9          13.3       0.5X
-readBinary(len) (DELTA_BYTE_ARRAY single-value)             64             67  
         3         16.5          60.6       0.1X
+readBytes (INT32)                                            4              4  
         0        236.3           4.2       1.0X
+readShorts (INT32)                                           9              9  
         2        117.6           8.5       0.5X
+readUnsignedIntegers (INT32 -> Long)                         9              9  
         1        117.6           8.5       0.5X
+readIntegersAsLongs (INT32 -> Long)                          4              4  
         0        286.8           3.5       1.2X
+readIntegersAsDoubles (INT32 -> Double)                      4              4  
         0        258.1           3.9       1.1X
+readUnsignedLongs (INT64 -> Decimal(20,0))                  28             29  
         0         36.9          27.1       0.2X
+skipBytes                                                    6              6  
         0        175.1           5.7       0.7X
+skipShorts                                                   6              6  
         1        175.4           5.7       0.7X
+readByte (INT32 single-value)                               14             14  
         1         76.5          13.1       0.3X
+readShort (INT32 single-value)                              14             14  
         0         76.6          13.1       0.3X
+readInteger (INT32 single-value)                            14             14  
         0         76.6          13.1       0.3X
+readLong (INT64 single-value)                               16             16  
         0         67.3          14.9       0.3X
+readBinary(len) (DELTA_BYTE_ARRAY single-value)             63             65  
         2         16.6          60.2       0.1X
 
 
diff --git 
a/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-jdk25-results.txt 
b/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-jdk25-results.txt
index fe7b64c3834b..ef6274f71249 100644
--- a/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-jdk25-results.txt
+++ b/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-jdk25-results.txt
@@ -2,92 +2,94 @@
 DELTA_BINARY_PACKED INT32
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1010-azure
+OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_BINARY_PACKED INT32:                Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readIntegers, constant                                2              2         
  0        487.1           2.1       1.0X
-skipIntegers, constant                                3              3         
  0        364.8           2.7       0.7X
-readIntegers, monotonic                               3              4         
  0        303.1           3.3       0.6X
-skipIntegers, monotonic                               3              3         
  0        365.3           2.7       0.7X
-readIntegers, small-delta random                      4              4         
  0        241.3           4.1       0.5X
-skipIntegers, small-delta random                      4              4         
  0        278.7           3.6       0.6X
-readIntegers, wide random                             5              5         
  0        201.4           5.0       0.4X
-skipIntegers, wide random                             5              5         
  0        225.6           4.4       0.5X
+readIntegers, constant                                2              2         
  0        473.1           2.1       1.0X
+skipIntegers, constant                                2              2         
  0        604.4           1.7       1.3X
+readIntegers, monotonic                               2              2         
  0        473.5           2.1       1.0X
+skipIntegers, monotonic                               2              2         
  0        607.2           1.6       1.3X
+readIntegers, small-delta random                      3              3         
  0        333.4           3.0       0.7X
+skipIntegers, small-delta random                      3              3         
  0        391.2           2.6       0.8X
+readIntegers, wide random                             4              4         
  0        271.5           3.7       0.6X
+skipIntegers, wide random                             4              4         
  0        294.7           3.4       0.6X
 
 
 
================================================================================================
 DELTA_BINARY_PACKED INT64
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1010-azure
+OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_BINARY_PACKED INT64:                Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readLongs, constant                                   6              7         
  1        163.0           6.1       1.0X
-skipLongs, constant                                   7              7         
  0        152.1           6.6       0.9X
-readLongs, monotonic                                  8              8         
  1        139.1           7.2       0.9X
-skipLongs, monotonic                                  7              7         
  0        152.0           6.6       0.9X
-readLongs, small-delta random                         9              9         
  0        122.7           8.2       0.8X
-skipLongs, small-delta random                         8              8         
  0        133.9           7.5       0.8X
-readLongs, wide random                               11             11         
  0         94.4          10.6       0.6X
-skipLongs, wide random                               10             10         
  0        100.9           9.9       0.6X
+readLongs, constant                                   2              2         
  0        497.0           2.0       1.0X
+skipLongs, constant                                   2              2         
  0        583.4           1.7       1.2X
+readLongs, monotonic                                  2              2         
  0        496.7           2.0       1.0X
+skipLongs, monotonic                                  2              2         
  0        588.6           1.7       1.2X
+readLongs, small-delta random                         3              3         
  0        342.8           2.9       0.7X
+skipLongs, small-delta random                         3              3         
  0        392.5           2.5       0.8X
+readLongs, wide random                                6              6         
  0        189.2           5.3       0.4X
+skipLongs, wide random                                5              5         
  0        197.4           5.1       0.4X
 
 
 
================================================================================================
 DELTA_BYTE_ARRAY
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1010-azure
+OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_BYTE_ARRAY:                         Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readBinary, no overlap, len=16                       37             38         
  2         28.2          35.5       1.0X
-skipBinary, no overlap, len=16                       42             43         
  2         25.2          39.7       0.9X
-readBinary, half overlap, len=16                     43             44         
  2         24.3          41.2       0.9X
-skipBinary, half overlap, len=16                     48             49         
  2         21.8          45.9       0.8X
-readBinary, full overlap, len=16                     44             47         
  4         24.0          41.7       0.9X
-skipBinary, full overlap, len=16                     48             50         
  2         21.6          46.3       0.8X
-readBinary, half overlap, len=64                     44             45         
  2         23.8          42.0       0.8X
-skipBinary, half overlap, len=64                     49             53         
  4         21.6          46.3       0.8X
+readBinary, no overlap, len=16                       27             31         
  3         38.3          26.1       1.0X
+skipBinary, no overlap, len=16                       32             32         
  0         33.2          30.2       0.9X
+readBinary, half overlap, len=16                     33             34         
  1         31.5          31.7       0.8X
+skipBinary, half overlap, len=16                     38             39         
  1         27.6          36.2       0.7X
+readBinary, full overlap, len=16                     34             34         
  1         31.2          32.1       0.8X
+skipBinary, full overlap, len=16                     38             39         
  1         27.3          36.7       0.7X
+readBinary, half overlap, len=64                     34             35         
  1         30.5          32.7       0.8X
+skipBinary, half overlap, len=64                     38             39         
  1         27.6          36.2       0.7X
 
 
 
================================================================================================
 DELTA_LENGTH_BYTE_ARRAY
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1010-azure
+OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_LENGTH_BYTE_ARRAY:                  Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readBinary, payloadLen=8                             22             22         
  0         48.7          20.5       1.0X
-skipBinary, payloadLen=8                             11             11         
  0         97.0          10.3       2.0X
-readBinary, payloadLen=32                            21             22         
  0         48.9          20.5       1.0X
-skipBinary, payloadLen=32                            11             11         
  0         97.0          10.3       2.0X
-readBinary, payloadLen=128                           24             24         
  1         43.7          22.9       0.9X
-skipBinary, payloadLen=128                           11             11         
  1         97.1          10.3       2.0X
-readBinary, payloadLen=512                           51             53         
  1         20.5          48.7       0.4X
-skipBinary, payloadLen=512                           11             11         
  0         97.1          10.3       2.0X
+readBinary, payloadLen=8                             16             17         
  1         63.7          15.7       1.0X
+skipBinary, payloadLen=8                              6              6         
  0        182.4           5.5       2.9X
+readBinary, payloadLen=32                            16             17         
  1         64.5          15.5       1.0X
+skipBinary, payloadLen=32                             6              6         
  0        182.7           5.5       2.9X
+readBinary, payloadLen=128                           19             19         
  1         55.7          18.0       0.9X
+skipBinary, payloadLen=128                            6              6         
  0        182.4           5.5       2.9X
+readBinary, payloadLen=512                           42             43         
  1         25.1          39.8       0.4X
+skipBinary, payloadLen=512                            6              6         
  0        182.7           5.5       2.9X
 
 
 
================================================================================================
 Variant reads
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1010-azure
+OpenJDK 64-Bit Server VM 25.0.3+9-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 Variant reads:                                   Best Time(ms)   Avg Time(ms)  
 Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
-------------------------------------------------------------------------------------------------------------------------------
-readBytes (INT32)                                            9             10  
         1        115.6           8.6       1.0X
-readShorts (INT32)                                           9             10  
         1        116.0           8.6       1.0X
-readUnsignedIntegers (INT32 -> Long)                         9              9  
         1        117.1           8.5       1.0X
-readUnsignedLongs (INT64 -> Decimal(20,0))                 211            223  
        27          5.0         201.5       0.0X
-skipBytes                                                    9              9  
         0        122.2           8.2       1.1X
-skipShorts                                                   9              9  
         0        122.3           8.2       1.1X
-readByte (INT32 single-value)                               13             13  
         0         80.1          12.5       0.7X
-readShort (INT32 single-value)                              14             15  
         1         72.7          13.7       0.6X
-readInteger (INT32 single-value)                            14             15  
         0         72.9          13.7       0.6X
-readLong (INT64 single-value)                               16             17  
         1         64.3          15.6       0.6X
-readBinary(len) (DELTA_BYTE_ARRAY single-value)             79             81  
         2         13.3          74.9       0.1X
+readBytes (INT32)                                            5              5  
         0        211.3           4.7       1.0X
+readShorts (INT32)                                           9              9  
         1        120.9           8.3       0.6X
+readUnsignedIntegers (INT32 -> Long)                        10             10  
         0        105.8           9.5       0.5X
+readIntegersAsLongs (INT32 -> Long)                          4              4  
         0        283.9           3.5       1.3X
+readIntegersAsDoubles (INT32 -> Double)                      4              4  
         0        253.0           4.0       1.2X
+readUnsignedLongs (INT64 -> Decimal(20,0))                  28             29  
         0         36.8          27.2       0.2X
+skipBytes                                                    6              6  
         0        166.5           6.0       0.8X
+skipShorts                                                   6              6  
         0        166.8           6.0       0.8X
+readByte (INT32 single-value)                               12             12  
         0         86.2          11.6       0.4X
+readShort (INT32 single-value)                              13             13  
         1         81.6          12.3       0.4X
+readInteger (INT32 single-value)                            14             14  
         0         74.7          13.4       0.4X
+readLong (INT64 single-value)                               16             16  
         1         66.9          14.9       0.3X
+readBinary(len) (DELTA_BYTE_ARRAY single-value)             64             66  
         3         16.3          61.3       0.1X
 
 
diff --git a/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-results.txt 
b/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-results.txt
index 9ff1678901e9..b3dc35eea94e 100644
--- a/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-results.txt
+++ b/sql/core/benchmarks/VectorizedDeltaReaderBenchmark-results.txt
@@ -2,92 +2,94 @@
 DELTA_BINARY_PACKED INT32
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_BINARY_PACKED INT32:                Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readIntegers, constant                                2              2         
  0        482.3           2.1       1.0X
-skipIntegers, constant                                3              3         
  0        335.4           3.0       0.7X
-readIntegers, monotonic                               3              3         
  0        314.9           3.2       0.7X
-skipIntegers, monotonic                               3              3         
  0        335.1           3.0       0.7X
-readIntegers, small-delta random                      4              4         
  0        257.5           3.9       0.5X
-skipIntegers, small-delta random                      4              4         
  0        269.5           3.7       0.6X
-readIntegers, wide random                             5              5         
  0        209.3           4.8       0.4X
-skipIntegers, wide random                             5              5         
  0        218.2           4.6       0.5X
+readIntegers, constant                                3              3         
  0        374.8           2.7       1.0X
+skipIntegers, constant                                2              2         
  0        612.8           1.6       1.6X
+readIntegers, monotonic                               3              3         
  0        374.3           2.7       1.0X
+skipIntegers, monotonic                               2              2         
  0        612.0           1.6       1.6X
+readIntegers, small-delta random                      4              4         
  0        297.3           3.4       0.8X
+skipIntegers, small-delta random                      2              3         
  0        426.7           2.3       1.1X
+readIntegers, wide random                             4              4         
  0        240.3           4.2       0.6X
+skipIntegers, wide random                             3              3         
  0        307.3           3.3       0.8X
 
 
 
================================================================================================
 DELTA_BINARY_PACKED INT64
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_BINARY_PACKED INT64:                Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readLongs, constant                                   5              6         
  1        191.0           5.2       1.0X
-skipLongs, constant                                   6              6         
  0        170.1           5.9       0.9X
-readLongs, monotonic                                  7              7         
  0        144.9           6.9       0.8X
-skipLongs, monotonic                                  6              6         
  0        170.1           5.9       0.9X
-readLongs, small-delta random                         8              8         
  0        134.8           7.4       0.7X
-skipLongs, small-delta random                         7              7         
  0        152.8           6.5       0.8X
-readLongs, wide random                               11             11         
  0         97.8          10.2       0.5X
-skipLongs, wide random                               10             10         
  0        106.4           9.4       0.6X
+readLongs, constant                                   2              2         
  0        535.0           1.9       1.0X
+skipLongs, constant                                   2              2         
  0        607.1           1.6       1.1X
+readLongs, monotonic                                  2              2         
  0        536.2           1.9       1.0X
+skipLongs, monotonic                                  2              2         
  0        605.8           1.7       1.1X
+readLongs, small-delta random                         3              3         
  0        367.0           2.7       0.7X
+skipLongs, small-delta random                         2              2         
  0        426.4           2.3       0.8X
+readLongs, wide random                                6              6         
  0        187.1           5.3       0.3X
+skipLongs, wide random                                5              5         
  0        194.8           5.1       0.4X
 
 
 
================================================================================================
 DELTA_BYTE_ARRAY
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_BYTE_ARRAY:                         Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readBinary, no overlap, len=16                       36             37         
  1         29.2          34.2       1.0X
-skipBinary, no overlap, len=16                       41             41         
  1         25.8          38.7       0.9X
-readBinary, half overlap, len=16                     42             43         
  1         25.0          39.9       0.9X
-skipBinary, half overlap, len=16                     48             50         
  2         21.6          46.2       0.7X
-readBinary, full overlap, len=16                     42             44         
  2         24.8          40.3       0.8X
-skipBinary, full overlap, len=16                     48             49         
  1         21.8          45.9       0.7X
-readBinary, half overlap, len=64                     42             44         
  1         24.8          40.4       0.8X
-skipBinary, half overlap, len=64                     47             49         
  1         22.2          45.1       0.8X
+readBinary, no overlap, len=16                       27             28         
  1         38.6          25.9       1.0X
+skipBinary, no overlap, len=16                       32             33         
  1         32.8          30.5       0.8X
+readBinary, half overlap, len=16                     33             34         
  1         31.4          31.8       0.8X
+skipBinary, half overlap, len=16                     39             40         
  1         26.9          37.2       0.7X
+readBinary, full overlap, len=16                     34             35         
  0         30.5          32.8       0.8X
+skipBinary, full overlap, len=16                     40             40         
  0         26.4          37.9       0.7X
+readBinary, half overlap, len=64                     35             35         
  0         30.3          33.0       0.8X
+skipBinary, half overlap, len=64                     39             40         
  1         26.6          37.6       0.7X
 
 
 
================================================================================================
 DELTA_LENGTH_BYTE_ARRAY
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 DELTA_LENGTH_BYTE_ARRAY:                  Best Time(ms)   Avg Time(ms)   
Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
------------------------------------------------------------------------------------------------------------------------
-readBinary, payloadLen=8                             22             25         
  2         48.1          20.8       1.0X
-skipBinary, payloadLen=8                             11             12         
  1         95.8          10.4       2.0X
-readBinary, payloadLen=32                            22             26         
  3         48.0          20.9       1.0X
-skipBinary, payloadLen=32                            11             12         
  1         97.6          10.2       2.0X
-readBinary, payloadLen=128                           26             29         
  2         40.0          25.0       0.8X
-skipBinary, payloadLen=128                           11             12         
  1         96.0          10.4       2.0X
-readBinary, payloadLen=512                           54             62         
  4         19.3          51.9       0.4X
-skipBinary, payloadLen=512                           11             13         
  2         95.7          10.4       2.0X
+readBinary, payloadLen=8                             17             19         
  2         63.1          15.9       1.0X
+skipBinary, payloadLen=8                              6              6         
  0        175.2           5.7       2.8X
+readBinary, payloadLen=32                            17             17         
  1         62.3          16.0       1.0X
+skipBinary, payloadLen=32                             6              6         
  0        175.3           5.7       2.8X
+readBinary, payloadLen=128                           19             19         
  0         55.1          18.1       0.9X
+skipBinary, payloadLen=128                            6              6         
  1        174.9           5.7       2.8X
+readBinary, payloadLen=512                           38             40         
  1         27.2          36.7       0.4X
+skipBinary, payloadLen=512                            6              6         
  0        174.8           5.7       2.8X
 
 
 
================================================================================================
 Variant reads
 
================================================================================================
 
-OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1011-azure
+OpenJDK 64-Bit Server VM 17.0.19+10-LTS on Linux 6.17.0-1018-azure
 AMD EPYC 7763 64-Core Processor
 Variant reads:                                   Best Time(ms)   Avg Time(ms)  
 Stdev(ms)    Rate(M/s)   Per Row(ns)   Relative
 
-------------------------------------------------------------------------------------------------------------------------------
-readBytes (INT32)                                            7              7  
         0        145.8           6.9       1.0X
-readShorts (INT32)                                           7              8  
         1        140.7           7.1       1.0X
-readUnsignedIntegers (INT32 -> Long)                         7              7  
         0        143.3           7.0       1.0X
-readUnsignedLongs (INT64 -> Decimal(20,0))                 227            239  
        25          4.6         216.4       0.0X
-skipBytes                                                    8              8  
         0        136.8           7.3       0.9X
-skipShorts                                                   8              8  
         0        136.6           7.3       0.9X
-readByte (INT32 single-value)                               12             12  
         1         85.8          11.7       0.6X
-readShort (INT32 single-value)                              12             12  
         0         85.9          11.6       0.6X
-readInteger (INT32 single-value)                            12             12  
         0         86.1          11.6       0.6X
-readLong (INT64 single-value)                               14             15  
         1         73.4          13.6       0.5X
-readBinary(len) (DELTA_BYTE_ARRAY single-value)             71             77  
         5         14.7          68.2       0.1X
+readBytes (INT32)                                            5              5  
         0        202.0           5.0       1.0X
+readShorts (INT32)                                           9              9  
         0        115.1           8.7       0.6X
+readUnsignedIntegers (INT32 -> Long)                         9              9  
         0        121.4           8.2       0.6X
+readIntegersAsLongs (INT32 -> Long)                          4              4  
         0        291.1           3.4       1.4X
+readIntegersAsDoubles (INT32 -> Double)                      4              4  
         0        258.8           3.9       1.3X
+readUnsignedLongs (INT64 -> Decimal(20,0))                  28             28  
         0         37.6          26.6       0.2X
+skipBytes                                                    6              7  
         1        165.5           6.0       0.8X
+skipShorts                                                   7              7  
         0        158.4           6.3       0.8X
+readByte (INT32 single-value)                               14             14  
         0         75.4          13.3       0.4X
+readShort (INT32 single-value)                              14             14  
         0         75.4          13.3       0.4X
+readInteger (INT32 single-value)                            14             14  
         0         75.4          13.3       0.4X
+readLong (INT64 single-value)                               15             16  
         0         68.1          14.7       0.3X
+readBinary(len) (DELTA_BYTE_ARRAY single-value)             62             64  
         1         17.0          58.7       0.1X
 
 
diff --git 
a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/ParquetDictionary.java
 
b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/ParquetDictionary.java
index ffdb94ee3765..aba5e1996a2e 100644
--- 
a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/ParquetDictionary.java
+++ 
b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/ParquetDictionary.java
@@ -19,8 +19,6 @@ package org.apache.spark.sql.execution.datasources.parquet;
 
 import org.apache.spark.sql.execution.vectorized.Dictionary;
 
-import java.math.BigInteger;
-
 public final class ParquetDictionary implements Dictionary {
   private org.apache.parquet.column.Dictionary dictionary;
   private boolean needTransform = false;
@@ -68,7 +66,7 @@ public final class ParquetDictionary implements Dictionary {
       // whenever dictionary is available.
       // Here we lazily decode it to the original signed long value then 
convert to decimal(20, 0).
       long signed = dictionary.decodeToLong(id);
-      return new BigInteger(Long.toUnsignedString(signed)).toByteArray();
+      return VectorizedReaderBase.unsignedLongToBytesBigEndian(signed);
     } else {
       return dictionary.decodeToBinary(id).getBytesUnsafe();
     }
diff --git 
a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/ParquetVectorUpdaterFactory.java
 
b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/ParquetVectorUpdaterFactory.java
index 90e4c3e04f81..8a72d2e5e731 100644
--- 
a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/ParquetVectorUpdaterFactory.java
+++ 
b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/ParquetVectorUpdaterFactory.java
@@ -717,6 +717,8 @@ public class ParquetVectorUpdaterFactory {
   }
 
   private static class UnsignedLongUpdater implements ParquetVectorUpdater {
+    private final byte[] unsignedLongScratch = new byte[9];
+
     @Override
     public void readValues(
         int total,
@@ -736,8 +738,9 @@ public class ParquetVectorUpdaterFactory {
         int offset,
         WritableColumnVector values,
         VectorizedValuesReader valuesReader) {
-      byte[] bytes = new 
BigInteger(Long.toUnsignedString(valuesReader.readLong())).toByteArray();
-      values.putByteArray(offset, bytes);
+      int start = VectorizedReaderBase.encodeUnsignedLongBigEndian(
+          valuesReader.readLong(), unsignedLongScratch);
+      values.putByteArray(offset, unsignedLongScratch, start, 9 - start);
     }
 
     @Override
@@ -747,8 +750,8 @@ public class ParquetVectorUpdaterFactory {
         WritableColumnVector dictionaryIds,
         Dictionary dictionary) {
       long signed = dictionary.decodeToLong(dictionaryIds.getDictId(offset));
-      byte[] unsigned = new 
BigInteger(Long.toUnsignedString(signed)).toByteArray();
-      values.putByteArray(offset, unsigned);
+      int start = VectorizedReaderBase.encodeUnsignedLongBigEndian(signed, 
unsignedLongScratch);
+      values.putByteArray(offset, unsignedLongScratch, start, 9 - start);
     }
   }
 
diff --git 
a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedDeltaBinaryPackedReader.java
 
b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedDeltaBinaryPackedReader.java
index 7b56e1ebf239..6abea3b40066 100644
--- 
a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedDeltaBinaryPackedReader.java
+++ 
b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedDeltaBinaryPackedReader.java
@@ -17,7 +17,6 @@
 package org.apache.spark.sql.execution.datasources.parquet;
 
 import java.io.IOException;
-import java.math.BigInteger;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 
@@ -70,6 +69,9 @@ public class VectorizedDeltaBinaryPackedReader extends 
VectorizedReaderBase {
   private int remainingInBlock = 0; // values in current block still to be read
   private int remainingInMiniBlock = 0; // values in current mini block still 
to be read
   private long[] unpackedValuesBuffer;
+  // Scratch buffer for narrowing long -> int during bulk readIntegers.
+  // Allocated eagerly in initFromPage, sized to miniBlockSizeInValues.
+  private int[] intScratchBuffer;
 
   private ByteBufferInputStream in;
 
@@ -95,6 +97,7 @@ public class VectorizedDeltaBinaryPackedReader extends 
VectorizedReaderBase {
     this.totalValueCount = BytesUtils.readUnsignedVarInt(in);
     this.bitWidths = new int[miniBlockNumInABlock];
     this.unpackedValuesBuffer = new long[miniBlockSizeInValues];
+    this.intScratchBuffer = new int[miniBlockSizeInValues];
     // read the first value
     firstValue = BytesUtils.readZigZagVarLong(in);
   }
@@ -140,7 +143,32 @@ public class VectorizedDeltaBinaryPackedReader extends 
VectorizedReaderBase {
 
   @Override
   public void readIntegers(int total, WritableColumnVector c, int rowId) {
-    readValues(total, c, rowId, (w, r, v) -> w.putInt(r, (int) v));
+    readBulkIntegers(total, c, rowId);
+  }
+
+  @Override
+  public void readIntegersAsLongs(int total, WritableColumnVector c, int 
rowId) {
+    // Delta decoder already works on long[]; skip the int narrowing and write 
longs directly.
+    readBulkLongs(total, c, rowId);
+  }
+
+  @Override
+  public void readIntegersAsDoubles(int total, WritableColumnVector c, int 
rowId) {
+    checkReadBounds(total);
+    int remaining = total;
+    if (valuesRead == 0) {
+      c.putDouble(rowId, (double) firstValue);
+      lastValueRead = firstValue;
+      rowId++;
+      remaining--;
+    }
+    readBulkLoop(remaining, c, rowId,
+        (col, r, buf, s, n) -> {
+          for (int i = s; i < s + n; i++) {
+            col.putDouble(r + i - s, (double) buf[i]);
+          }
+        });
+    valuesRead += total;
   }
 
   // Based on VectorizedPlainValuesReader.readIntegersWithRebase
@@ -170,13 +198,13 @@ public class VectorizedDeltaBinaryPackedReader extends 
VectorizedReaderBase {
   @Override
   public void readUnsignedLongs(int total, WritableColumnVector c, int rowId) {
     readValues(total, c, rowId, (w, r, v) -> {
-      w.putByteArray(r, new 
BigInteger(Long.toUnsignedString(v)).toByteArray());
+      putUnsignedLongAsBigInteger(w, r, v);
     });
   }
 
   @Override
   public void readLongs(int total, WritableColumnVector c, int rowId) {
-    readValues(total, c, rowId, WritableColumnVector::putLong);
+    readBulkLongs(total, c, rowId);
   }
 
   @Override
@@ -215,6 +243,111 @@ public class VectorizedDeltaBinaryPackedReader extends 
VectorizedReaderBase {
     skipValues(total);
   }
 
+  // ---- Bulk read helpers for readIntegers / readLongs 
----------------------------
+  //
+  // The generic readValues() path dispatches a lambda per value.  For the two 
most
+  // common callers (readIntegers, readLongs) we can do much better: compute a 
prefix
+  // sum over the unpacked deltas in-place, then bulk-copy the result into the 
column
+  // vector with putInts / putLongs (backed by System.arraycopy on-heap).
+
+  /**
+   * Callback for writing a chunk of prefix-summed absolute values from
+   * {@code unpackedValuesBuffer} into a column vector.  Called once per 
mini-block
+   * (not per value), so lambda overhead is negligible.
+   */
+  @FunctionalInterface
+  private interface BulkWriter {
+    void write(WritableColumnVector c, int rowId, long[] values, int start, 
int count);
+  }
+
+  /** Narrows long[] -> int[] scratch and bulk-writes via putInts. */
+  private void bulkWriteInts(WritableColumnVector c, int rowId,
+      long[] buf, int start, int count) {
+    for (int i = start; i < start + count; i++) {
+      intScratchBuffer[i] = (int) buf[i];
+    }
+    c.putInts(rowId, count, intScratchBuffer, start);
+  }
+
+  private void readBulkIntegers(int total, WritableColumnVector c, int rowId) {
+    checkReadBounds(total);
+    int remaining = total;
+    if (valuesRead == 0) {
+      c.putInt(rowId, (int) firstValue);
+      lastValueRead = firstValue;
+      rowId++;
+      remaining--;
+    }
+    readBulkLoop(remaining, c, rowId, this::bulkWriteInts);
+    valuesRead += total;
+  }
+
+  private void readBulkLongs(int total, WritableColumnVector c, int rowId) {
+    checkReadBounds(total);
+    int remaining = total;
+    if (valuesRead == 0) {
+      c.putLong(rowId, firstValue);
+      lastValueRead = firstValue;
+      rowId++;
+      remaining--;
+    }
+    readBulkLoop(remaining, c, rowId,
+        (col, r, buf, s, n) -> col.putLongs(r, n, buf, s));
+    valuesRead += total;
+  }
+
+  private void checkReadBounds(int total) {
+    if (valuesRead + total > totalValueCount) {
+      throw new ParquetDecodingException(
+          "No more values to read. Total values read:  " + valuesRead + ", 
total count: "
+              + totalValueCount + ", trying to read " + total + " more.");
+    }
+  }
+
+  /** Mini-block iteration loop shared by readBulkIntegers and readBulkLongs. 
*/
+  private void readBulkLoop(int remaining, WritableColumnVector c, int rowId,
+      BulkWriter writer) {
+    while (remaining > 0) {
+      int n;
+      try {
+        n = loadMiniBlockBulk(remaining, c, rowId, writer);
+      } catch (IOException e) {
+        throw new ParquetDecodingException("Error reading mini block.", e);
+      }
+      rowId += n;
+      remaining -= n;
+    }
+  }
+
+  /**
+   * Loads the next mini-block (if needed), prefix-sums the deltas in-place, 
and
+   * delegates the type-specific column write to {@code writer}.
+   */
+  private int loadMiniBlockBulk(int remaining, WritableColumnVector c, int 
rowId,
+      BulkWriter writer) throws IOException {
+    if (remainingInBlock == 0) readBlockHeader();
+    if (remainingInMiniBlock == 0) unpackMiniBlock();
+
+    int start = miniBlockSizeInValues - remainingInMiniBlock;
+    int count = Math.min(remaining, remainingInMiniBlock);
+
+    // Prefix-sum: convert raw deltas -> absolute values in-place.
+    long running = lastValueRead;
+    long minDelta = minDeltaInCurrentBlock;
+    long[] buf = unpackedValuesBuffer;
+    for (int i = start; i < start + count; i++) {
+      running += minDelta + buf[i];
+      buf[i] = running;
+    }
+    lastValueRead = running;
+
+    writer.write(c, rowId, buf, start, count);
+
+    remainingInBlock -= count;
+    remainingInMiniBlock -= count;
+    return count;
+  }
+
   private void readValues(int total, WritableColumnVector c, int rowId,
       IntegerOutputWriter outputWriter) {
     if (valuesRead + total > totalValueCount) {
@@ -240,7 +373,7 @@ public class VectorizedDeltaBinaryPackedReader extends 
VectorizedReaderBase {
       rowId += n;
       remaining -= n;
     }
-    valuesRead = total - remaining;
+    valuesRead += total;
   }
 
 
@@ -328,4 +461,12 @@ public class VectorizedDeltaBinaryPackedReader extends 
VectorizedReaderBase {
     readValues(total, null, -1, (w, r, v) -> {});
   }
 
+  // Reusable buffer for unsigned long -> BigInteger encoding (9 bytes: sign + 
8 value bytes).
+  private final byte[] unsignedLongScratch = new byte[9];
+
+  private void putUnsignedLongAsBigInteger(WritableColumnVector c, int rowId, 
long v) {
+    int start = encodeUnsignedLongBigEndian(v, unsignedLongScratch);
+    c.putByteArray(rowId, unsignedLongScratch, start, 9 - start);
+  }
+
 }
diff --git 
a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedReaderBase.java
 
b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedReaderBase.java
index 77bb9340e526..f5ab1a68bea6 100644
--- 
a/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedReaderBase.java
+++ 
b/sql/core/src/main/java/org/apache/spark/sql/execution/datasources/parquet/VectorizedReaderBase.java
@@ -27,6 +27,44 @@ import 
org.apache.spark.sql.execution.vectorized.WritableColumnVector;
  */
 public class VectorizedReaderBase extends ValuesReader implements 
VectorizedValuesReader {
 
+  /**
+   * Encodes an unsigned long as a minimal big-endian two's-complement byte 
array
+   * compatible with {@link java.math.BigInteger} encoding, written into
+   * {@code scratch[start .. 8]} (length = 9 - start). {@code scratch} must 
have length >= 9.
+   *
+   * <p>This avoids the per-value overhead of
+   * {@code new BigInteger(Long.toUnsignedString(v)).toByteArray()} which 
allocates a
+   * String, a BigInteger, and a byte[] on every call.
+   */
+  static int encodeUnsignedLongBigEndian(long v, byte[] scratch) {
+    // Minimal BigInteger-compatible length is bitLength/8 + 1, so the
+    // encoding occupies scratch[start .. 8]; the loop runs once past the
+    // significant bytes, which writes the 0x00 sign byte when one is needed.
+    int start = 8 - (64 - Long.numberOfLeadingZeros(v)) / 8;
+    long x = v;
+    for (int i = 8; i >= start; i--) {
+      scratch[i] = (byte) x;
+      x >>>= 8;
+    }
+    return start;
+  }
+
+  /**
+   * Convenience: encodes an unsigned long and returns a new byte[] with the 
minimal
+   * BigInteger-compatible encoding. Use {@link 
#encodeUnsignedLongBigEndian(long, byte[])}
+   * with a reusable buffer in hot paths to avoid allocation.
+   */
+  static byte[] unsignedLongToBytesBigEndian(long v) {
+    int len = (64 - Long.numberOfLeadingZeros(v)) / 8 + 1;
+    byte[] out = new byte[len];
+    long x = v;
+    for (int i = len - 1; i >= 0 && x != 0; i--) {
+      out[i] = (byte) x;
+      x >>>= 8;
+    }
+    return out;
+  }
+
   @Override
   public void skip() {
     throw SparkUnsupportedOperationException.apply();
diff --git 
a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/parquet/VectorizedDeltaReaderBenchmark.scala
 
b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/parquet/VectorizedDeltaReaderBenchmark.scala
index 40e08d9870c7..b97faeaf57b6 100644
--- 
a/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/parquet/VectorizedDeltaReaderBenchmark.scala
+++ 
b/sql/core/src/test/scala/org/apache/spark/sql/execution/datasources/parquet/VectorizedDeltaReaderBenchmark.scala
@@ -29,7 +29,7 @@ import org.apache.parquet.io.api.Binary
 
 import org.apache.spark.benchmark.{Benchmark, BenchmarkBase}
 import org.apache.spark.sql.execution.vectorized.OnHeapColumnVector
-import org.apache.spark.sql.types.{BinaryType, ByteType, DecimalType, 
IntegerType, LongType, ShortType}
+import org.apache.spark.sql.types.{BinaryType, ByteType, DecimalType, 
DoubleType, IntegerType, LongType, ShortType}
 
 /**
  * Low-level benchmark for the three Parquet delta-encoding decoders:
@@ -299,6 +299,7 @@ object VectorizedDeltaReaderBenchmark extends BenchmarkBase 
{
     val byteVec = new OnHeapColumnVector(NUM_ROWS, ByteType)
     val shortVec = new OnHeapColumnVector(NUM_ROWS, ShortType)
     val longVec = new OnHeapColumnVector(NUM_ROWS, LongType)
+    val doubleVec = new OnHeapColumnVector(NUM_ROWS, DoubleType)
     val unsignedLongVec = new OnHeapColumnVector(NUM_ROWS, DecimalType(20, 0))
 
     def newIntReader(): VectorizedDeltaBinaryPackedReader = {
@@ -320,7 +321,14 @@ object VectorizedDeltaReaderBenchmark extends 
BenchmarkBase {
     benchmark.addCase("readUnsignedIntegers (INT32 -> Long)") { _ =>
       newIntReader().readUnsignedIntegers(NUM_ROWS, longVec, 0)
     }
+    benchmark.addCase("readIntegersAsLongs (INT32 -> Long)") { _ =>
+      newIntReader().readIntegersAsLongs(NUM_ROWS, longVec, 0)
+    }
+    benchmark.addCase("readIntegersAsDoubles (INT32 -> Double)") { _ =>
+      newIntReader().readIntegersAsDoubles(NUM_ROWS, doubleVec, 0)
+    }
     benchmark.addCase("readUnsignedLongs (INT64 -> Decimal(20,0))") { _ =>
+      unsignedLongVec.reset()
       newLongReader().readUnsignedLongs(NUM_ROWS, unsignedLongVec, 0)
     }
     benchmark.addCase("skipBytes") { _ => newIntReader().skipBytes(NUM_ROWS) }


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

Reply via email to