8306374: (bf) Improve performance of DirectCharBuffer::append(CharSequence[,int,int])

Reviewed-by: liach, alanb
This commit is contained in:
Brian Burkhalter 2023-04-26 16:37:18 +00:00
parent a18191fee8
commit d0e8aec041
6 changed files with 142 additions and 19 deletions

View File

@ -446,6 +446,69 @@ class Direct$Type$Buffer$RW$$BO$
// --- Methods to support CharSequence ---
#if[rw]
private static final int APPEND_BUF_SIZE = 1024;
private $Type$Buffer appendChars(CharSequence csq, int start, int end) {
Objects.checkFromToIndex(start, end, csq.length());
int pos = position();
int lim = limit();
int rem = (pos <= lim) ? lim - pos : 0;
int length = end - start;
if (length > rem)
throw new BufferOverflowException();
char[] buf = new char[Math.min(APPEND_BUF_SIZE, length)];
int index = pos;
while (start < end) {
int count = end - start;
if (count > buf.length)
count = buf.length;
if (csq instanceof String str) {
str.getChars(start, start + count, buf, 0);
} else if (csq instanceof StringBuilder sb) {
sb.getChars(start, start + count, buf, 0);
} else if (csq instanceof StringBuffer sb) {
sb.getChars(start, start + count, buf, 0);
}
putArray(index, buf, 0, count);
start += count;
index += count;
}
position(pos + length);
return this;
}
#end[rw]
public $Type$Buffer append(CharSequence csq) {
#if[rw]
if (csq instanceof StringBuilder)
return appendChars(csq, 0, csq.length());
return super.append(csq);
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
public $Type$Buffer append(CharSequence csq, int start, int end) {
#if[rw]
if (csq instanceof String || csq instanceof StringBuffer ||
csq instanceof StringBuilder)
return appendChars(csq, start, end);
return super.append(csq, start, end);
#else[rw]
throw new ReadOnlyBufferException();
#end[rw]
}
public CharBuffer subSequence(int start, int end) {
int pos = position();
int lim = limit();

View File

@ -1319,7 +1319,7 @@ public abstract sealed class $Type$Buffer
return put(index, src, 0, src.length);
}
private $Type$Buffer putArray(int index, $type$[] src, int offset, int length) {
$Type$Buffer putArray(int index, $type$[] src, int offset, int length) {
#if[rw]
if (
#if[char]

View File

@ -41,6 +41,9 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Random;
#end[byte]
#if[char]
import java.util.function.IntFunction;
#end[char]
public class Basic$Type$
@ -646,15 +649,24 @@ public class Basic$Type$
{cslen/2, cslen + 1} // end > cslen
};
for (CharSequence csq : csqs) {
// append() should throw BufferOverflowException
tryCatch(b, BufferOverflowException.class, () ->
CharBuffer.allocate(cslen/8).append(csq, cslen/4, cslen/2));
IntFunction<CharBuffer>[] producers = new IntFunction[] {
(i) -> CharBuffer.allocate(i),
(i) -> ByteBuffer.allocateDirect(2*i).asCharBuffer()
};
// append() should throw IndexOutOfBoundsException
for (int[] bds : bounds)
tryCatch(b, IndexOutOfBoundsException.class, () ->
CharBuffer.allocate(cslen + 1).append(csq, bds[0], bds[1]));
for (IntFunction<CharBuffer> f : producers) {
for (CharSequence csq : csqs) {
// append() should throw BufferOverflowException
final CharBuffer cbBOE = f.apply(cslen/8);
tryCatch(cbBOE, BufferOverflowException.class, () ->
cbBOE.append(csq, cslen/4, cslen/2));
// append() should throw IndexOutOfBoundsException
final CharBuffer cbIOOBE = f.apply(cslen + 1);
for (int[] bds : bounds)
tryCatch(cbIOOBE, IndexOutOfBoundsException.class, () ->
cbIOOBE.append(csq, bds[0], bds[1]));
}
}
// end 8306623

View File

@ -26,7 +26,7 @@
* @bug 4413135 4414911 4416536 4416562 4418782 4471053 4472779 4490253 4523725
* 4526177 4463011 4660660 4661219 4663521 4782970 4804304 4938424 5029431
* 5071718 6231529 6221101 6234263 6535542 6591971 6593946 6795561 7190219
* 7199551 8065556 8149469 8230665 8237514 8306623
* 7199551 8065556 8149469 8230665 8237514 8306374 8306623
* @modules java.base/java.nio:open
* java.base/jdk.internal.misc
* @author Mark Reinhold

View File

@ -42,6 +42,9 @@ import java.nio.*;
import java.util.function.IntFunction;
public class BasicChar
extends Basic
@ -646,15 +649,24 @@ public class BasicChar
{cslen/2, cslen + 1} // end > cslen
};
for (CharSequence csq : csqs) {
// append() should throw BufferOverflowException
tryCatch(b, BufferOverflowException.class, () ->
CharBuffer.allocate(cslen/8).append(csq, cslen/4, cslen/2));
IntFunction<CharBuffer>[] producers = new IntFunction[] {
(i) -> CharBuffer.allocate(i),
(i) -> ByteBuffer.allocateDirect(2*i).asCharBuffer()
};
// append() should throw IndexOutOfBoundsException
for (int[] bds : bounds)
tryCatch(b, IndexOutOfBoundsException.class, () ->
CharBuffer.allocate(cslen + 1).append(csq, bds[0], bds[1]));
for (IntFunction<CharBuffer> f : producers) {
for (CharSequence csq : csqs) {
// append() should throw BufferOverflowException
final CharBuffer cbBOE = f.apply(cslen/8);
tryCatch(cbBOE, BufferOverflowException.class, () ->
cbBOE.append(csq, cslen/4, cslen/2));
// append() should throw IndexOutOfBoundsException
final CharBuffer cbIOOBE = f.apply(cslen + 1);
for (int[] bds : bounds)
tryCatch(cbIOOBE, IndexOutOfBoundsException.class, () ->
cbIOOBE.append(csq, bds[0], bds[1]));
}
}
// end 8306623

View File

@ -44,7 +44,7 @@ import org.openjdk.jmh.annotations.Warmup;
@Fork(1)
public class CharBufferAppend {
static final int SIZE = 8192;
static final int SIZE = 32768;
static String str;
static StringBuffer strbuf;
@ -138,4 +138,40 @@ public class CharBufferAppend {
hbDst.clear();
return hbDst.append(strbld, SIZE/4, 3*SIZE/4);
}
@Benchmark
public CharBuffer appendStringToDirect() {
dbDst.clear();
return dbDst.append(str);
}
@Benchmark
public CharBuffer appendStringBufferToDirect() {
dbDst.clear();
return dbDst.append(strbuf);
}
@Benchmark
public CharBuffer appendStringBuilderToDirect() {
dbDst.clear();
return dbDst.append(strbld);
}
@Benchmark
public CharBuffer appendSubStringToDirect() {
dbDst.clear();
return dbDst.append(str, SIZE/4, 3*SIZE/4);
}
@Benchmark
public CharBuffer appendSubStringBufferToDirect() {
dbDst.clear();
return dbDst.append(strbuf, SIZE/4, 3*SIZE/4);
}
@Benchmark
public CharBuffer appendSubStringBuilderToDirect() {
dbDst.clear();
return dbDst.append(strbld, SIZE/4, 3*SIZE/4);
}
}