Avoid slicing memory segments unnecessarily (#13906)

No point in copying the memory segment instances when slicing, they are stateless.
This commit is contained in:
Armin Braun 2024-10-15 20:53:54 +02:00 committed by GitHub
parent f69b196ef2
commit 331323f1b9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 39 additions and 13 deletions

View File

@ -530,7 +530,29 @@ abstract class MemorySegmentIndexInput extends IndexInput
@Override
public final MemorySegmentIndexInput clone() {
final MemorySegmentIndexInput clone = buildSlice((String) null, 0L, this.length);
ensureOpen();
ensureAccessible();
final MemorySegmentIndexInput clone;
if (segments.length == 1) {
clone =
new SingleSegmentImpl(
toString(),
null, // clones don't have an Arena, as they can't close)
segments[0],
length,
chunkSizePower,
confined);
} else {
clone =
new MultiSegmentImpl(
toString(),
null, // clones don't have an Arena, as they can't close)
segments,
((MultiSegmentImpl) this).offset,
length,
chunkSizePower,
confined);
}
try {
clone.seek(getFilePointer());
} catch (IOException ioe) {
@ -592,26 +614,30 @@ abstract class MemorySegmentIndexInput extends IndexInput
MemorySegmentIndexInput buildSlice(String sliceDescription, long offset, long length) {
ensureOpen();
ensureAccessible();
final MemorySegment[] slices;
final boolean isClone = offset == 0 && length == this.length;
if (isClone) {
slices = segments;
} else {
final long sliceEnd = offset + length;
final int startIndex = (int) (offset >>> chunkSizePower);
final int endIndex = (int) (sliceEnd >>> chunkSizePower);
// we always allocate one more slice, the last one may be a 0 byte one after truncating with
// asSlice():
slices = ArrayUtil.copyOfSubArray(segments, startIndex, endIndex + 1);
final long sliceEnd = offset + length;
final int startIndex = (int) (offset >>> chunkSizePower);
final int endIndex = (int) (sliceEnd >>> chunkSizePower);
// set the last segment's limit for the sliced view.
slices[slices.length - 1] = slices[slices.length - 1].asSlice(0L, sliceEnd & chunkSizeMask);
// we always allocate one more slice, the last one may be a 0 byte one after truncating with
// asSlice():
final MemorySegment slices[] = ArrayUtil.copyOfSubArray(segments, startIndex, endIndex + 1);
// set the last segment's limit for the sliced view.
slices[slices.length - 1] = slices[slices.length - 1].asSlice(0L, sliceEnd & chunkSizeMask);
offset = offset & chunkSizeMask;
offset = offset & chunkSizeMask;
}
final String newResourceDescription = getFullSliceDescription(sliceDescription);
if (slices.length == 1) {
return new SingleSegmentImpl(
newResourceDescription,
null, // clones don't have an Arena, as they can't close)
slices[0].asSlice(offset, length),
isClone ? slices[0] : slices[0].asSlice(offset, length),
length,
chunkSizePower,
confined);