[master] Integrated: 8320761: [Lilliput] Implement compact identity hashcode
Roman Kennke
rkennke at openjdk.org
Wed Jan 22 16:46:16 UTC 2025
On Tue, 17 Dec 2024 15:07:01 GMT, Roman Kennke <rkennke at openjdk.org> wrote:
> This reimplements identity hash-code such that it allocates the space for the i-hash only on-demand. The idea is that most objects never get i-hashed, and therefore we don't want to penalize those objects which don't by carrying 32 unused bits for no reason.
>
> I'm proposing that we only reserve two bits in the header to track the state of an object:
>
> - One bit to indicate that an object has been i-hashed
> - Another bit to indicate that an object has been 'expanded' to hold the i-hash in a field.
>
> The transition would then be as follows:
> 1. Object starts out with state 00: not i-hashed, and not expanded.
> 2. The first time when Object.identityHashCode() is called, advance the state to 01 (i-hashed, but not expanded). Generate an i-hash based on the object's address, and return that.
> 3. Whenever Object.identityHashCode() is called in that state, and as long as that object stays at its address, keep generating the i-hash based on its address.
> 4. As soon as the object gets moved to a new address (by the GC), advance the state to 11 (i-hashed and expanded), generate the i-hash based on the original address one last time, and write it to the hidden field in the expanded object.
> 5. Whenever Object.identityHashCode() is called in that state, read the hidden field and return the i-hashed that has been stored there.
>
> Transitioning to the 'expanded' state does not necessarily mean that the object actually needs to be expanded. The offset of the hidden field for any class is computed at class-loading-time. That field may fit into any gaps in the field layout, including alignment gaps at the end of an object. Only when no such gaps are found, we need to actually expand the object during GC. That appears to happen approx 50% of the time.
>
> For a discussion why it is not a problem to expand objects during GC, see here: [https://wiki.openjdk.org/display/lilliput/Compact+Identity+Hashcode](https://wiki.openjdk.org/display/lilliput/Compact+Identity+Hashcode)
>
> One caveat is that ParallelGC is currently does not supported. Parallel's full-GC precalculates block sizes based on the assumption that objects don't grow. I will propose a fix for this as a follow-up, but it's likely a somewhat complex change.
>
> I ran some I-hash heavy benchmarks (e.g. SPECjvm compiler benchmarks), and have not seen a performance difference. It would be nice to make some micro-benchmarks for the various scenarios (e.g. is it faster to compute the i-hash or read it from memory?), and compare that with the ...
This pull request has now been integrated.
Changeset: 33f69df3
Author: Roman Kennke <rkennke at openjdk.org>
URL: https://git.openjdk.org/lilliput/commit/33f69df31c403e2e5c030e7b5a9f1b475cee74fb
Stats: 889 lines in 65 files changed: 725 ins; 16 del; 148 mod
8320761: [Lilliput] Implement compact identity hashcode
Reviewed-by: stuefe
-------------
PR: https://git.openjdk.org/lilliput/pull/192
More information about the lilliput-dev
mailing list