andygrove opened a new pull request, #23881:
URL: https://github.com/apache/datafusion/pull/23881

   ## Which issue does this PR close?
   
   N/A
   
   ## Rationale for this change
   
   Two Spark functions allocated a `String` per row purely to render a small,
   bounded amount of text:
   
   - `bin` called `format!("{value:b}")` for every row.
   - `char` called `ch.to_string()` for every row — a heap allocation for a 
single
     character.
   
   In both cases the output has a known upper bound (64 binary digits for an 
`i64`,
   4 bytes for a UTF-8 character), so the rendering fits in a stack buffer and 
the
   result can be appended straight to a pre-sized builder.
   
   ## What changes are included in this PR?
   
   `math/bin.rs`:
   
   - `spark_bin` now writes digits right-aligned into a caller-supplied `[u8; 
64]`
     and returns a `&str` borrowed from it, instead of returning an owned 
`String`.
   - The `collect::<StringArray>()` becomes an explicit loop over a
     `StringBuilder::with_capacity`, sized at 8 digits per row.
   - Negative values still render as their two's-complement bit pattern, 
matching
     `{:b}`. The digit loop is a `loop`, not a `while`, so zero renders as `"0"`
     rather than the empty string.
   
   `string/char.rs`:
   
   - `ch.to_string()` becomes `ch.encode_utf8(&mut encoded)` against a `[u8; 4]`
     hoisted out of the loop.
   
   Output is unchanged in both cases.
   
   ## Are these changes tested?
   
   Existing coverage pins the behaviour. `spark/math/bin.slt` asserts concrete
   output for the cases the rewrite had to get right: zero, negative values,
   `i64::MIN` (`-9223372036854775808`), `i64::MAX`, and `-2147483648` /
   `-32768` widened from narrower integer types. `spark/string/char.slt` covers
   the negative-input empty string, the null path, and characters on both sides 
of
   the ASCII boundary (`char(256)` and above wrap via `% 256`).
   
   All 119 `spark/math` and `spark/string` sqllogictest files pass, along with 
the
   258 `datafusion-spark` unit tests.
   
   A new benchmark, `datafusion/spark/benches/bin.rs`, covers `bin` at 1024 and
   8192 rows with 20% nulls, over two value distributions: small values that 
render
   to a handful of digits, and full-range values that render to the maximum 64.
   `char` already had `datafusion/spark/benches/char.rs`.
   
   ### Benchmarks
   
   Criterion, `apache/main` @ `f1ab86dad` as baseline. Median of the reported
   change interval.
   
   | Benchmark | 1024 | 8192 |
   | --- | --- | --- |
   | `bin/small` | −75.7% | −73.7% |
   | `bin/wide` | −47.8% | −49.8% |
   
   `char` (1024 rows): −76.1%.
   
   ## Are there any user-facing changes?
   
   No. Both functions produce byte-identical output; this is purely an 
allocation
   change.
   


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