8361209: (bf) Use CharSequence::getChars for StringCharBuffer bulk get methods

Reviewed-by: rriggs, alanb
This commit is contained in:
Brian Burkhalter 2025-08-12 17:39:14 +00:00
parent 4c03e5938d
commit d023982600
3 changed files with 102 additions and 9 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -97,7 +97,13 @@ final class StringCharBuffer // package-private
return str.charAt(index + offset);
}
// ## Override bulk get methods for better performance
@Override
CharBuffer getArray(int index, char[] dst, int dstOffset, int length) {
// Note: the variable "offset" is defined and set in the superclass
int srcOffset = offset + index;
str.getChars(srcOffset, srcOffset + length, dst, dstOffset);
return this;
}
public final CharBuffer put(char c) {
throw new ReadOnlyBufferException();

View file

@ -950,12 +950,15 @@ public abstract sealed class $Type$Buffer
return get(index, dst, 0, dst.length);
}
private $Type$Buffer getArray(int index, $type$[] dst, int offset, int length) {
if (
//
// This method does not perform bounds checking which it expects
// will have been done by the caller
//
$Type$Buffer getArray(int index, $type$[] dst, int offset, int length) {
#if[char]
isAddressable() &&
assert isAddressable();
#end[char]
((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
if (((long)length << $LG_BYTES_PER_VALUE$) > Bits.JNI_COPY_TO_ARRAY_THRESHOLD) {
long bufAddr = address + ((long)index << $LG_BYTES_PER_VALUE$);
long dstOffset =
ARRAY_BASE_OFFSET + ((long)offset << $LG_BYTES_PER_VALUE$);
@ -1116,6 +1119,10 @@ public abstract sealed class $Type$Buffer
return this;
}
//
// This method does not perform bounds checking which it expects
// will have been done by the caller
//
void putBuffer(int pos, $Type$Buffer src, int srcPos, int n) {
#if[rw]
Object srcBase = src.base();
@ -1150,9 +1157,13 @@ public abstract sealed class $Type$Buffer
#if[char]
} else { // src.isAddressable() == false
assert StringCharBuffer.class.isInstance(src);
int posMax = pos + n;
for (int i = pos, j = srcPos; i < posMax; i++, j++)
put(i, src.get(j));
if (this.hb != null && src instanceof StringCharBuffer scb) {
scb.getArray(srcPos, this.hb, pos, n);
} else {
int posMax = pos + n;
for (int i = pos, j = srcPos; i < posMax; i++, j++)
put(i, src.get(j));
}
}
#end[char]
#else[rw]
@ -1342,6 +1353,10 @@ public abstract sealed class $Type$Buffer
return put(index, src, 0, src.length);
}
//
// This method does not perform bounds checking which it expects
// will have been done by the caller
//
$Type$Buffer putArray(int index, $type$[] src, int offset, int length) {
#if[rw]
if (

View file

@ -0,0 +1,72 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.openjdk.bench.java.nio;
import java.nio.CharBuffer;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
/**
* Benchmark for bulk get methods of a {@code CharBuffer} created from a
* {@code CharSequence}.
*/
@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@State(Scope.Benchmark)
@Fork(1)
public class StringCharBufferBulkTransfer {
private static final int LENGTH = 16384;
char[] buf = new char[LENGTH];
CharBuffer cb = CharBuffer.wrap(new String(buf));
char[] dst = new char[LENGTH];
CharBuffer cbw = CharBuffer.allocate(LENGTH);
@Benchmark
public void absoluteBulkGet() {
cb.get(0, dst, 0, dst.length);
}
@Benchmark
public void relativeBulkGet() {
cb.get(dst, 0, dst.length);
cb.position(0);
}
@Benchmark
public void getChars() {
cb.getChars(0, LENGTH, dst, 0);
}
@Benchmark
public void absoluteBulkPut() {
cbw.put(0, cb, 0, dst.length);
}
}