yaooqinn opened a new pull request, #12166:
URL: https://github.com/apache/gluten/pull/12166

   ## What changes were proposed in this pull request?
   
   In `ColumnarCachedBatchSerializer.convertInternalRowToCachedBatch`,
   three values that are constant for the lifetime of the per-partition
   `Iterator[CachedBatch]` were being re-evaluated on every `next()` call:
   
   1. `BackendsApiManager.getBackendName` -- invoked twice per batch
      (once for the JNI runtime context, once for `getNativeHandle`)
   2. `GlutenConfig.get.getConf(COLUMNAR_TABLE_CACHE_PARTITION_STATS_ENABLED)`
      -- `GlutenConfig.get` allocates a fresh `GlutenConfig(SQLConf.get)`
      on every call (`GlutenConfig.scala` L584-L586) plus a `SparkConf`
      hashmap lookup
   3. `ColumnarBatchSerializerJniWrapper.create(Runtimes.contextInstance(...))`
      -- JNI wrapper construction
   
   This PR hoists all three out of `next()` into the `mapPartitions` body,
   alongside the `structSchema` value that the same block already hoists
   for the identical many-small-batch GC-pressure reason. Only the
   per-batch `handle = ColumnarBatches.getNativeHandle(backendName, batch)`
   remains inside `next()`, since it genuinely depends on the batch.
   
   ## Why are the changes needed?
   
   The block immediately preceding `new Iterator[CachedBatch]` already
   hoists `structSchema` with a comment explicitly citing many-small-batch
   GC pressure. The three values listed above belong in the same hoist --
   they are all partition-iterator-scoped constants whose per-batch
   re-evaluation produces zero behavioral signal but consumes allocator /
   JNI traffic on every batch.
   
   `GlutenConfig.get` is especially worth hoisting because it eagerly
   constructs a new `GlutenConfig(SQLConf.get)` on each invocation rather
   than returning a cached instance:
   
   ```scala
   def get: GlutenConfig = new GlutenConfig(SQLConf.get)
   ```
   
   ## Does this PR introduce any user-facing change?
   
   No. Wire format is byte-identical; `partitionStatsEnabled` is now
   captured once at partition start instead of re-read per batch, which
   matches the existing semantics of `SQLConf.get` in Spark task
   execution (already TaskContext-thread-snapshot) -- no observable
   difference from the per-batch re-read.
   
   ## How was this patch tested?
   
   The change is a pure refactor with byte-identical wire output. The
   behavior is fully covered by the existing serializer test suites:
   
   - `ColumnarCachedBatchKryoSuite` -- 6 tests (incl. V1 wire back-compat 
contract)
   - `ColumnarCachedBatchKryoBoundaryProbeBugSuite` -- 1 test (#12147)
   
   All 7 tests green locally on `-Pspark-4.1 -Pscala-2.13`.
   
   No new test file is added. Cross-batch reuse of the hoisted JNI
   wrapper is safe because (a) `ColumnarBatchSerializerJniWrapper` holds
   only a `final Runtime runtime` reference with no mutable per-batch
   state, and (b) the native side (`cpp/core/jni/JniWrapper.cc` L1280-L1325)
   constructs a fresh `ctx->createColumnarBatchSerializer(nullptr)` on
   every JNI call -- the wrapper is a stateless route to the runtime.
   
   ---
   
   **Was this patch authored or co-authored using generative AI tooling?**
   No
   


-- 
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