sunchao commented on code in PR #7106:
URL: https://github.com/apache/datafusion-comet/pull/7106#discussion_r4320381503


##########
native/spark-expr/src/conversion_funcs/cast.rs:
##########
@@ -874,6 +875,44 @@ fn cast_binary_to_string<O: OffsetSizeTrait>(
         .downcast_ref::<GenericByteArray<GenericBinaryType<O>>>()
         .unwrap();
 
+    // `new String(bytes, UTF_8)` leaves valid UTF-8 unchanged. Check the 
whole value buffer once:
+    // when it is valid, reuse the input's buffers instead of copying every 
value. Otherwise rows
+    // inside its valid prefix are copied without being checked again, and 
only the rest, starting
+    // at the first invalid byte (which may sit under a null or outside a 
slice), are decoded.
+    let mut valid_prefix = "";
+    if matches!(
+        spark_cast_options.binary_output_style,
+        None | Some(BinaryOutputStyle::Utf8)
+    ) {
+        let data = input.value_data();

Review Comment:
   [P2] [P2] Avoid validating the entire backing buffer for every slice. 
`BinaryArray::slice` retains the original value buffer, so `input.value_data()` 
includes bytes outside the logical array. Casting consecutive slices now 
rescans all those bytes on every invocation, whereas the previous decoder 
processed only visible values. This affects existing binary-to-string casts 
over sliced batches, including chunked aggregate output. For 262,144 valid 
64-byte values emitted as 32 slices of 8,192 rows, conversion increased from 
3.29 ms to 24.99 ms (7.59×), with identical output. Could we retain the 
previous path for sliced arrays, or slice the values and rebase offsets before 
validation? That preserves the whole-array improvement without making 
conversion cost scale with unrelated backing data.
   
   Evidence: Ran `CARGO_TARGET_DIR=/tmp/comet-pr7106-kernel/target cargo run 
--release --offline --manifest-path /tmp/comet-pr7106-head-kernel/Cargo.toml -- 
--chunks-only`. The harness uses Arrow 59.3.0 and helpers verified 
byte-for-byte against the supplied base and head. It builds a 16 MiB 
BinaryArray of 262,144 valid 64-byte values, casts `parent.slice(i * 8192, 
8192)` for i=0..31, and checks output equality. Median timings over seven 
alternating groups were base=3.291 ms and head=24.987 ms. A separate 128-row 
slice of an 8 MiB buffer measured 5.690→205.707 µs. Arrow 59.3.0 
`GenericByteArray::slice` clones the full value buffer. DataFusion 55.2.0 
`MaterializedAggregateOutput::next_batch` emits these shared-buffer slices via 
`self.batch.slice(self.offset, length)`. Measurements isolate conversion cost 
rather than whole-query runtime.



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