vbhanuchander-lang opened a new pull request, #17603:
URL: https://github.com/apache/iceberg/pull/17603

   Closes #16003
   
   ### What
   
   `SparkValueWriters.UUIDWriter` carried a TODO for exactly this:
   
   ```java
   // TODO: direct conversion from string to byte buffer
   UUID uuid = UUID.fromString(s.toString());
   encoder.writeFixed(UUIDUtil.convertToByteBuffer(uuid, BUFFER.get()).array());
   ```
   
   Two intermediate objects per row, on a write path: `s.toString()` allocates 
a `String` and decodes UTF-8, then `UUID.fromString` parses it with a regex, 
splits and `Long.parseLong` to build a `UUID` that is immediately destructured 
back into two longs for the buffer.
   
   This adds `UUIDUtil.convertToByteBuffer(byte[] uuidText, int offset, int 
length, ByteBuffer reuse)`, which reads the canonical text straight from its 
ASCII bytes into the caller's buffer, plus a two-argument overload. The Spark 
writer now calls it with `s.getBytes()`. No `String`, no `UUID`, and the 
thread-local buffer is still reused.
   
   ### One deliberate behaviour difference
   
   The new path is **stricter** than `UUID.fromString`, which zero-extends 
short groups — `UUID.fromString("1-2-3-4-5")` parses successfully today. Only 
the canonical 8-4-4-4-12 form is accepted, upper or lower case.
   
   I chose strict because these bytes land in a data file, so accepting a 
non-canonical string would persist a value the writer never really validated. 
It is a narrowing, though, so if you would rather preserve the lenient 
behaviour exactly I am happy to change it — there is a test pinning the current 
choice either way.
   
   ### Tests
   
   `TestUUIDUtil`, 14 tests, all passing:
   
   - agreement with `UUID.fromString` over **1000 random UUIDs** — this is the 
property that matters, since the method replaces it on the write path
   - the all-zero, all-ones and sign-bit boundaries (`80000000-...`, 
`7fffffff-...`), where a sloppy shift or a sign-extension bug would show up
   - case insensitivity, buffer reuse returning the same instance, and reading 
at an offset
   - seven non-canonical inputs rejected (too short, too long, no dashes, wrong 
separator, non-hex digit, trailing space, empty) rather than silently producing 
different bytes
   - an explicit test documenting that `"1-2-3-4-5"` parses via 
`UUID.fromString` and is rejected here
   
   ```
   TestUUIDUtil: tests=14 failures=0 errors=0
   ```
   
   `:iceberg-api:checkstyleMain`, `:iceberg-api:checkstyleTest`, 
`:iceberg-api:spotlessCheck`, 
`:iceberg-spark:iceberg-spark-4.1_2.13:checkstyleMain` and `spotlessCheck` all 
pass, as do the Spark 4.1 Avro write tests.
   
   ### Spark versions
   
   Applied to v3.5, v4.0 and v4.1, matching #17482. Only one Spark version 
configures in a local Gradle build at a time, so I verified the gates against 
4.1; the change is byte-identical in all three.
   
   ### Not included
   
   No JMH benchmark. The allocation reduction is structural — two objects and a 
regex parse removed per value — so I did not want to attach a synthetic number 
to it without a harness you would trust. Happy to add one if you would like the 
figure.


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