Another option is to make the internal stored hash a long and then the first
part can be used to track whether it has been computed and then just cast the
long to an int to retrieve the value. If it has been computed, one bit is
flipped in the upper 32 bits. Then a read is just a single long read + int
cast, and a write is just the computed hashCode plus an OR.
The main downside of course is that it adds 3 bytes to each string (of course
alignment and padding etc might change that overhead).
@Stable private long hash; // Default to 0
public int hashCode() {
long h = hash;
if ((h & ~(1L << 32)) == 0) // if calculated bit is not set, the calculate
hash = h = (1L << 32) | (isLatin1()
? StringLatin1.hashCode(value)
: StringUTF16.hashCode(value));
return (int)h;
}
Cheers,
√
Viktor Klang
Software Architect, Java Platform Group
Oracle
________________________________
From: core-libs-dev <[email protected]> on behalf of
[email protected] <[email protected]>
Sent: Friday, 11 April 2025 11:04
To: Chen Liang <[email protected]>
Cc: core-libs-dev <[email protected]>
Subject: Re: java.lang.String hashCode and @Stable ?
________________________________
From: "Chen Liang" <[email protected]>
To: "Remi Forax" <[email protected]>, "core-libs-dev"
<[email protected]>
Sent: Thursday, April 10, 2025 8:16:39 PM
Subject: Re: java.lang.String hashCode and @Stable ?
Hi Remi,
I think this is probably due to these fields being added too early - the stable
on string byte array is also added lately.
That said, I don't think adding stable on both fields completely resolves the
constant folding issues around string hash code. The current code can only
constant fold non-zero hash; a zero hash is folded to a read to hash field,
which cannot fold further because it's a read of the default value from a
stable field.
A solution may be to change hashIsZero to a byte field indicating 3 states -
hash unset (0), hash computed to field, hash computed and is zero. This allows
the zero hash to constant fold as well at the cost of non-constant hash access
performance, as now there are two reads.
yes,
and obviously, it has to be done without introducing a perf regression if the
String is not constant folded.
I think it would be nice to try that as a follow-up of JDK-8354300.
Also this reminds me of https://bugs.openjdk.org/browse/JDK-8332249 - maybe
Method::hashCode was hot because the string hash code could not fold.
Usually in framework like Spring, Method are cached either by the framework or
by java.lang.Class own cache so the Method itself is rarely a constant.
Regards, Chen
regards,
Rémi
________________________________
From: core-libs-dev <[email protected]> on behalf of Remi Forax
<[email protected]>
Sent: Thursday, April 10, 2025 4:18 AM
To: core-libs-dev <[email protected]>
Subject: java.lang.String hashCode and @Stable ?
Question,
why String.hash and String.hashIsZero are not declared @Stable ?
regards,
Rémi