david-mollitor-db opened a new pull request, #58842:
URL: https://github.com/apache/spark/pull/58842
### What changes were proposed in this pull request?
Casting an integral (byte/short/int/long) or boolean value to string routed
through
`java.lang.String`: both the interpreted and codegen paths in `ToStringBase`
emitted
`UTF8String.fromString(String.valueOf(x))`, and
`UTF8String.fromString(String)` does
`str.getBytes(StandardCharsets.UTF_8)`. A single `CAST(<long> AS STRING)`
therefore
allocated a `java.lang.String`, its backing array, a re-encoded UTF-8
`byte[]`, and the
result `UTF8String` -- only the last two are essential.
This PR adds two `UTF8String` factories and uses them in `ToStringBase`:
- `UTF8String.fromLong(long)` writes the base-10 ASCII digits directly into
a single
`byte[]` (no intermediate `java.lang.String`).
- `UTF8String.fromBoolean(boolean)` returns a shared cached
`"true"`/`"false"` instance.
The integral and boolean cases are added before the existing
`String.valueOf` fallthrough in
both `ToStringBase` conversion paths (interpreted `castToStringDefault` and
codegen
`castToStringCode`). byte/short/int widen to long without changing the
decimal
representation; `Float`/`Double` and all other types keep the current
fallthrough.
### Why are the changes needed?
`CAST(<integral> AS STRING)` is a very common expression (key building,
string
concatenation, display), and the `java.lang.String` round-trip is avoidable
per-row
overhead. JFR allocation profiling of `AggregateBenchmark`'s "aggregate with
string key"
case (keys built with `cast(id & 1023 as string)`) attributed the bulk of
sampled
allocation to the cast's String round-trip. With this change the
`Long.toString` (~64%) and
`Arrays.copyOf(byte[])` (~32%) allocation sites collapse to ~0, leaving only
the irreducible
result allocation (`UTF8String.fromBytes`). Per-row allocation for these
casts drops from
~4 objects to one `byte[]` plus one `UTF8String`. Both `Cast` and
`ToPrettyString` (which
mix in `ToStringBase`) benefit.
### Does this PR introduce _any_ user-facing change?
No. The output is byte-identical to `String.valueOf`/`Long.toString`.
### How was this patch tested?
New `UTF8StringSuite` tests for `fromLong` (zero, sign and digit-count
boundaries,
`Integer`/`Long` MIN and MAX, values past int range, and a contiguous sweep
compared with
`String.valueOf`) and `fromBoolean`. Existing `CastWithAnsiOnSuite`,
`CastWithAnsiOffSuite`,
and `ToPrettyStringSuite` pass unchanged.
### Was this patch authored or co-authored using generative AI tooling?
Generated-by: Isaac
This pull request and its description were written by Isaac.
--
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]