-
Couldn't load subscription status.
- Fork 6.1k
8333893: Optimization for StringBuilder append boolean & null #19626
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5e815b6
0cbaa5a
f96cde4
27a3050
dd97cff
67be25c
7b3cf60
ad1af38
22d4512
b5ad8e7
1a012f1
3db11b2
fa72999
6be002a
7563577
9d9c8eb
d2dcc24
4df729c
d01d595
61196ec
3c55f15
0ede6ed
399c8ef
ae05477
d1fdcc1
457735c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,6 +32,7 @@ | |
| import java.util.function.IntConsumer; | ||
| import java.util.stream.Stream; | ||
| import java.util.stream.StreamSupport; | ||
| import jdk.internal.misc.Unsafe; | ||
| import jdk.internal.util.ArraysSupport; | ||
| import jdk.internal.util.DecimalDigits; | ||
| import jdk.internal.vm.annotation.IntrinsicCandidate; | ||
|
|
@@ -42,6 +43,8 @@ | |
| import static java.lang.String.checkOffset; | ||
|
|
||
| final class StringLatin1 { | ||
| private static final Unsafe UNSAFE = Unsafe.getUnsafe(); | ||
|
|
||
| public static char charAt(byte[] value, int index) { | ||
| checkIndex(index, value.length); | ||
| return (char)(value[index] & 0xff); | ||
|
|
@@ -824,6 +827,27 @@ static Stream<String> lines(byte[] value) { | |
| return StreamSupport.stream(LinesSpliterator.spliterator(value), false); | ||
| } | ||
|
|
||
| static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4) { | ||
| assert index >= 0 && index + 3 < length(val) : "Trusted caller missed bounds check"; | ||
| // Don't use the putChar method, Its instrinsic will cause C2 unable to combining values into larger stores. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. explicit array stores has the overhead of boundary checking. If putCharsAt of StringLatin1 is not implemented based on Unsafe, the performance will be worse than StringUTF16. Of course, this is a common problem. StringUTF16.putChar is equivalent to Unsafe.putChar, without boundary checking. I found in many test scenarios that the UTF16 version performs better than the StringLatin1 version. We may need to change some StringLatin1 related implementations to use Unsafe, otherwise users will turn off COMPACT_STRINGS to improve performance. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thank you for telling what the blocking issue is here. Does C2 not merge the bound checks when it does the merge stores? Interesting, and I think a fix from their side should be the way to go. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. MergeStore does not work when using StringUTF16.putChar, waiting for improvements from @eme64 |
||
| long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + index; | ||
| UNSAFE.putByte(val, address , (byte)(c1)); | ||
| UNSAFE.putByte(val, address + 1, (byte)(c2)); | ||
| UNSAFE.putByte(val, address + 2, (byte)(c3)); | ||
| UNSAFE.putByte(val, address + 3, (byte)(c4)); | ||
| } | ||
|
|
||
| static void putCharsAt(byte[] val, int index, int c1, int c2, int c3, int c4, int c5) { | ||
| assert index >= 0 && index + 4 < length(val) : "Trusted caller missed bounds check"; | ||
| // Don't use the putChar method, Its instrinsic will cause C2 unable to combining values into larger stores. | ||
| long address = Unsafe.ARRAY_BYTE_BASE_OFFSET + index; | ||
| UNSAFE.putByte(val, address , (byte)(c1)); | ||
| UNSAFE.putByte(val, address + 1, (byte)(c2)); | ||
| UNSAFE.putByte(val, address + 2, (byte)(c3)); | ||
| UNSAFE.putByte(val, address + 3, (byte)(c4)); | ||
| UNSAFE.putByte(val, address + 4, (byte)(c5)); | ||
| } | ||
|
|
||
| public static void putChar(byte[] val, int index, int c) { | ||
| //assert (canEncode(c)); | ||
| val[index] = (byte)(c); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should declare
countbeforeensureCapacitiyInternal. Same for append boolean.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Declaring count before ensureCapacityInternal will cause performance regression under x64. It took a lot of time to find this, but the underlying reason is still unclear.