Repository navigation
Decode and determine equality for strings directly from immutable byte segments - #856
Conversation
213cfe9 to
9ab6b04
Compare
|
Redundant Arrays.fill on the default (non-immutable) path. (minor regression) The diff removed the else: if (length > chararr.length) if(immutable) Arrays.fill(chararr, 0, length, '\0'); When length > 100, chararr was just allocated and is already zeroed, so the fill is a pure O(length) waste — on the path every default-configured consumer still uses. Restoring the else for the |
ef4dd55 to
a1b61dd
Compare
|
Restored conditional clearing so the legacy decoder clears reused scratch but leaves newly allocated arrays alone. Fixed empty-string reads and comparisons when variable-length storage is absent. Added regression tests for empty and null values with both recycler modes. |
64116bf to
41cac4b
Compare
41cac4b to
e2718b4
Compare
e2718b4 to
4c6b5e6
Compare
|
Gated direct segment string decoding and equality checks behind |
Extend the immutable segmented string fast path to equality checks used by primary-key matching. Decode VInts directly from captured byte-array segments instead of resolving each encoded byte through ByteData.get(). Keep the existing equality implementation for recycling and shared-memory data, and add segment-boundary, Unicode, surrogate-pair, read-state, and benchmark coverage.
4c6b5e6 to
ffa7775
Compare
This is a String decoding change I've wanted to make for years, and a string equality change that also shows up on read paths.
When decoding
StringfromSegmentedByteArray, every call resolvessegments[index]again, and with ZGC, that also means another reference load barrier. In an Images profile, those byte lookups while decoding strings accounted for about 1.6% of total process CPU.The immutability established by #853 lets this path load the segment table once and then process each contiguous
byte[]range directly. That same segmented traversal is also now used byisStringFieldEqual(...), which is primarily exercised by primary-key matching.The JDK has since seen a lot of investment in
Stringto support compact strings, so a contiguous ASCII range now goes directly to the specializedString(byte[], ..., ISO_8859_1)path. On JDK 19 and later, contiguous ranges also use the JDK ASCII decoder to identify and inflate the leading ASCII run through thecountPositivesintrinsic. Earlier releases retain the scalar path; JDK 17 exposed the decoder fast path but did not yet have the prefix-returning intrinsic and regressed on mixed strings.Benchmark
HollowObjectTypeReadStateShardBenchmark.testReadString, Azul JDK 25.0.4.1 on x86-64 with ZGC, 500 strings per operation, and a 10% probability ofU+123Echaracters. Both sides use non-recycling storage and the same seeded input:The additional JDK 19+ ASCII-prefix path, measured against the scalar path on Azul JDK 21.0.12.1 with ZGC on the same host and 500 strings per operation:
HollowObjectTypeReadStateShardBenchmark.testStringEquality, Azul JDK 25.0.4.1 with ZGC on the same host, 500 matching comparisons per operation, non-recycling storage, and the same seeded Unicode distribution:The equality method was added to the parent benchmark harness for this comparison; the parent implementation was unchanged.