Add fastpath implementation for Unpooled.copiedBuffer(CharSequence, Charset) when UTF-8 or US-ASCII is used (#10206)

Motivation:

We can make use of our optimized implementations for UTF-8 and US-ASCII if the user request a copy of a sequence for these charsets

Modifications:

- Add fastpath implementation
- Add unit tests

Result:

Fixes https://github.com/netty/netty/issues/10205
This commit is contained in:
Norman Maurer 2020-04-23 17:47:16 +02:00
parent a091d9df4e
commit 0c2c7c8f82
2 changed files with 63 additions and 0 deletions

View File

@ -18,6 +18,7 @@ package io.netty.buffer;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
import io.netty.buffer.CompositeByteBuf.ByteWrapper; import io.netty.buffer.CompositeByteBuf.ByteWrapper;
import io.netty.util.CharsetUtil;
import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.PlatformDependent;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
@ -579,6 +580,12 @@ public final class Unpooled {
public static ByteBuf copiedBuffer(CharSequence string, Charset charset) { public static ByteBuf copiedBuffer(CharSequence string, Charset charset) {
requireNonNull(string, "string"); requireNonNull(string, "string");
if (CharsetUtil.UTF_8.equals(charset)) {
return copiedBufferUtf8(string);
}
if (CharsetUtil.US_ASCII.equals(charset)) {
return copiedBufferAscii(string);
}
if (string instanceof CharBuffer) { if (string instanceof CharBuffer) {
return copiedBuffer((CharBuffer) string, charset); return copiedBuffer((CharBuffer) string, charset);
} }
@ -586,6 +593,36 @@ public final class Unpooled {
return copiedBuffer(CharBuffer.wrap(string), charset); return copiedBuffer(CharBuffer.wrap(string), charset);
} }
private static ByteBuf copiedBufferUtf8(CharSequence string) {
boolean release = true;
// Mimic the same behavior as other copiedBuffer implementations.
ByteBuf buffer = ALLOC.heapBuffer(ByteBufUtil.utf8Bytes(string));
try {
ByteBufUtil.writeUtf8(buffer, string);
release = false;
return buffer;
} finally {
if (release) {
buffer.release();
}
}
}
private static ByteBuf copiedBufferAscii(CharSequence string) {
boolean release = true;
// Mimic the same behavior as other copiedBuffer implementations.
ByteBuf buffer = ALLOC.heapBuffer(string.length());
try {
ByteBufUtil.writeAscii(buffer, string);
release = false;
return buffer;
} finally {
if (release) {
buffer.release();
}
}
}
/** /**
* Creates a new big-endian buffer whose content is a subregion of * Creates a new big-endian buffer whose content is a subregion of
* the specified {@code string} encoded in the specified {@code charset}. * the specified {@code string} encoded in the specified {@code charset}.

View File

@ -15,12 +15,14 @@
*/ */
package io.netty.buffer; package io.netty.buffer;
import io.netty.util.CharsetUtil;
import org.junit.Test; import org.junit.Test;
import org.mockito.Mockito; import org.mockito.Mockito;
import java.io.InputStream; import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.channels.ScatteringByteChannel; import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
@ -308,6 +310,30 @@ public class UnpooledTest {
assertEquals(0, buf2.refCnt()); assertEquals(0, buf2.refCnt());
} }
@Test
public void testCopiedBufferUtf8() {
testCopiedBufferCharSequence("Some UTF_8 like äÄ∏ŒŒ", CharsetUtil.UTF_8);
}
@Test
public void testCopiedBufferAscii() {
testCopiedBufferCharSequence("Some US_ASCII", CharsetUtil.US_ASCII);
}
@Test
public void testCopiedBufferSomeOtherCharset() {
testCopiedBufferCharSequence("Some ISO_8859_1", CharsetUtil.ISO_8859_1);
}
private static void testCopiedBufferCharSequence(CharSequence sequence, Charset charset) {
ByteBuf copied = copiedBuffer(sequence, charset);
try {
assertEquals(sequence, copied.toString(charset));
} finally {
copied.release();
}
}
@Test @Test
public void testCopiedBuffer() { public void testCopiedBuffer() {
ByteBuf copied = copiedBuffer(ByteBuffer.allocateDirect(16)); ByteBuf copied = copiedBuffer(ByteBuffer.allocateDirect(16));