Skip to content

Conversation

kohlschuetter
Copy link
Contributor

In an effort to further reduce the number of allocations, add support for Opaques backed by ByteBuffer or byte[] instances that may be mutable. Adjust the Opaque API to allow these mutable objects to be used in the context of hashmaps for reads, as well as for writes (by converting them to an immutable variant).

Also cache the hashCode value for immutable Opaques, which further reduces the computational overhead, and allows them to be used directly as keys in LockManager (see the change for SimpleLm).

We may frequently compare Opaques via HashMap.

Cache the #hashCode computation once computed.

Related: dCache#149
Signed-off-by: Christian Kohlschütter <christian@kohlschutter.com>
Currently, Opaque is merely a wrapper around byte[], which adds
hashCode/equals functionality, preventing mutations, so we can use it as
a key in a HashMap.

When we process a byte stream (from a ByteBuffer), we may want to look
up values from a HashMap. However, we would still need to create new
byte[]-backed Opaque objects for the lookup. This creates unnecessary
allocations.

Improve the Opaque interface to clarify that by itself, Opaques can be
mutable. Provide a #toImmutableOpaque() method which is used when
storing values in a Map.

Adjust FileTracker to use immutable Opaques when storing in a Map.

Provide a mutable Opaque implementation backed by a ByteBuffer, and
improve equals() for OpaqueImpl.

Add a small test case to ensure sanity.

Related: dCache#149
Signed-off-by: Christian Kohlschütter <christian@kohlschutter.com>
The SimpleLm keeps all data in memory; there is no obvious need to store
the keys as Base64 strings.

Use Opaque directly, ensuring that only immutable Opaque keys are used
for storing.

Related: dCache#149
Signed-off-by: Christian Kohlschütter <christian@kohlschutter.com>
Similar to mutable ByteBuffers, provide support for mutable byte[]
backing Opaque.

Related: dCache#149
Signed-off-by: Christian Kohlschütter <christian@kohlschutter.com>
... demonstrating the difference between mutable and immutable Opaques.

Related: dCache#149
Signed-off-by: Christian Kohlschütter <christian@kohlschutter.com>
@kohlschuetter kohlschuetter changed the title Opaque: Add support mutable byte buffers and arrays Opaque: Add support for mutable byte buffers and arrays Jun 30, 2025
That way, we don't have to declare the cache attributes for hashCode and
base64 when not required.

Related: dCache#149
Signed-off-by: Christian Kohlschütter <christian@kohlschutter.com>
OpaqueBufferImpl other = (OpaqueBufferImpl) o;
ByteBuffer otherBuf = other.buf;
int otherIndex = other.index;
for (int i = index, n = index + length, oi = otherIndex; i < n; i++, oi++) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use ByteBuffer#mismatch, which is based on vector operations

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately, ByteBuffer#mismatch starts checking at position(), which is not what we want (the underlying code would support that but it's not exposed).

It's actually also unlikely that we'll compare two buffer-backed Opaques. It's usually a buffer-backed opaque and an immutable byte[]-backed one in a HashMap.

The general use case is that we can read an entire message into a ByteBuffer, and then look up what we have in map without any further allocation.

if (o instanceof OpaqueImpl) {
return Arrays.equals(_opaque, ((OpaqueImpl) o)._opaque);
} else if (o instanceof OpaqueBufferImpl) {
OpaqueBufferImpl other = (OpaqueBufferImpl) o;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The general use case is that we can read an entire message into a ByteBuffer, and then look up what we have in map without any further allocation.

Compared to the original code of Opaque the "semantics" are unchanged (since Opaque was mutable).

@kofemann kofemann merged commit 01eea28 into dCache:master Jul 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants