On Thu, 19 Oct 2023 11:58:26 GMT, Claes Redestad <[email protected]> wrote:
>> @cl4es
>>
>>> Good, narrows it down to what's going on in `prepend(long, byte[],
>>> String)`. Might boil down to `System.arraycopy`. This method might not be
>>> optimized for tiny arrays on all platforms. Specializing for single-char
>>> case:
>>>
>>> ```java
>>> diff --git a/src/java.base/share/classes/java/lang/String.java
>>> b/src/java.base/share/classes/java/lang/String.java
>>> index 9b19d7e2ac1..6eb70925dab 100644
>>> --- a/src/java.base/share/classes/java/lang/String.java
>>> +++ b/src/java.base/share/classes/java/lang/String.java
>>> @@ -4723,7 +4723,11 @@ static void repeatCopyRest(byte[] buffer, int
>>> offset, int limit, int copied) {
>>> */
>>> void getBytes(byte[] dst, int dstBegin, byte coder) {
>>> if (coder() == coder) {
>>> - System.arraycopy(value, 0, dst, dstBegin << coder,
>>> value.length);
>>> + if (value.length == 1) {
>>> + dst[(dstBegin << coder)] = value[0];
>>> + } else {
>>> + System.arraycopy(value, 0, dst, dstBegin << coder,
>>> value.length);
>>> + }
>>> } else { // this.coder == LATIN && coder == UTF16
>>> StringLatin1.inflate(value, 0, dst, dstBegin, value.length);
>>> }
>>> ```
>>>
>>> .. seem to help the JIT do the right thing consistently, too:
>>>
>>> ```
>>> Benchmark Mode Cnt Score Error Units
>>> BigDecimals.testSmallToEngineeringString avgt 50 11,757 ± 0,480 ns/op
>>> ```
>>
>> In addition to #16244, will you submit a PR for this?
>
>> In addition to #16244, will you submit a PR for this?
>
> Once both #16244 and this has been integrated I want to revisit this. The
> effect of changing `getBytes(byte[], int, byte)` might have disappeared with
> #16244 since it better guarantees the JIT will constant fold the prefixes
> thoroughly. We've observed related issues with System.arraycopy, however, see
> https://bugs.openjdk.org/browse/JDK-8295496 - so I want to evaluate a few
> different options here, time allowing.
@cl4es @rgiulietti
Can I add scale2 method to StringLatin1? Like this:
package java.lang;
class StringLatin1 {
static String scale2(long value) {
long valueAbs = Math.abs(value);
long highInt = valueAbs / 100;
byte[] buf = new byte[Long.stringSize(highInt) + (value < 0 ? 4 : 3)];
int p = buf.length - 2;
writeDigitPair(buf, p, (int) (valueAbs % 100));
buf[--p] = '.';
getChars(highInt, p, buf);
if (value < 0) {
buf[0] = '-';
}
if (String.COMPACT_STRINGS) {
return new String(buf, LATIN1);
}
return new String(inflate(buf, 0, buf.length), UTF16);
}
}
class System {
private static void setJavaLangAccess() {
SharedSecrets.setJavaLangAccess(new JavaLangAccess() {
public String scale2(long i) {
return StringLatin1.scale2(i);
}
}
}
}
I think this is more readable than using MethodHandle.
-------------
PR Comment: https://git.openjdk.org/jdk/pull/16006#issuecomment-1775022048