Skip to content

Commit

Permalink
Polishing #2610
Browse files Browse the repository at this point in the history
Reduce code duplications. Add exact optimization to ASCII StringCodec. Tweak Javadoc.

Original pull request: #2768
  • Loading branch information
mp911de committed Feb 26, 2024
1 parent 68c89ae commit 6185ebd
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 54 deletions.
21 changes: 18 additions & 3 deletions src/main/java/io/lettuce/core/codec/StringCodec.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.*;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.StandardCharsets;

import io.lettuce.core.internal.LettuceAssert;
import io.netty.buffer.ByteBuf;
Expand Down Expand Up @@ -100,6 +104,16 @@ public int estimateSize(Object keyOrValue) {
return 0;
}

@Override
public boolean isEstimateExact() {

if (ascii) {
return true;
}

return ToByteBufEncoder.super.isEstimateExact();
}

@Override
public void encodeValue(String value, ByteBuf target) {
encode(value, target);
Expand Down Expand Up @@ -186,8 +200,8 @@ public void encode(String str, ByteBuf target) {
}

/**
* Calculate either the maximum number of bytes a string may occupy in a given character set or
* the average number of bytes it may hold.
* Calculate either the maximum number of bytes a string may occupy in a given character set or the average number of bytes
* it may hold.
*/
int sizeOf(String value, boolean estimate) {

Expand All @@ -205,4 +219,5 @@ int sizeOf(String value, boolean estimate) {

return (int) maxBytesPerChar * value.length();
}

}
7 changes: 4 additions & 3 deletions src/main/java/io/lettuce/core/codec/ToByteBufEncoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ public interface ToByteBufEncoder<K, V> {
int estimateSize(Object keyOrValue);

/**
* Returns true if {@link ToByteBufEncoder#estimateSize(Object)} returns exact size
* This is used as an optimisation to reduce memory allocations when encoding data
* Returns {@code true} if {@link #estimateSize(Object)} returns exact size This is used as an optimization to reduce memory
* allocations when encoding data.
*
* @return true if {@link ToByteBufEncoder#estimateSize(Object)} returns exact size
* @return {@code true} if {@link #estimateSize(Object)} returns exact size.
* @since 6.3.2
*/
default boolean isEstimateExact() {
return false;
Expand Down
83 changes: 35 additions & 48 deletions src/main/java/io/lettuce/core/protocol/CommandArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -547,9 +547,9 @@ static void writeInteger(ByteBuf target, long value) {

static class IntegerCache {

static final IntegerArgument cache[];
static final IntegerArgument[] cache;

static final IntegerArgument negativeCache[];
static final IntegerArgument[] negativeCache;

static {
int high = Integer.getInteger("io.lettuce.core.CommandArgs.IntegerCache", 128);
Expand Down Expand Up @@ -648,8 +648,8 @@ static void writeString(ByteBuf target, char[] value) {
IntegerArgument.writeInteger(target, value.length);
target.writeBytes(CRLF);

for (int i = 0; i < value.length; i++) {
target.writeByte((byte) value[i]);
for (char c : value) {
target.writeByte((byte) c);
}
target.writeBytes(CRLF);
}
Expand Down Expand Up @@ -681,29 +681,7 @@ static <K, V> KeyArgument<K, V> of(K key, RedisCodec<K, V> codec) {
void encode(ByteBuf target) {

if (codec instanceof ToByteBufEncoder) {

ToByteBufEncoder<K, V> toByteBufEncoder = (ToByteBufEncoder<K, V>) codec;

if (toByteBufEncoder.isEstimateExact()) {
target.writeByte('$');

IntegerArgument.writeInteger(target, toByteBufEncoder.estimateSize(key));
target.writeBytes(CRLF);

toByteBufEncoder.encodeKey(key, target);
target.writeBytes(CRLF);
} else {
ByteBuf temporaryBuffer = target.alloc().buffer(toByteBufEncoder.estimateSize(key) + 6);

try {

toByteBufEncoder.encodeKey(key, temporaryBuffer);
ByteBufferArgument.writeByteBuf(target, temporaryBuffer);
} finally {
temporaryBuffer.release();
}
}

CommandArgs.encode(target, (ToByteBufEncoder<K, K>) codec, key, ToByteBufEncoder::encodeKey);
return;
}

Expand Down Expand Up @@ -737,27 +715,7 @@ static <K, V> ValueArgument<K, V> of(V val, RedisCodec<K, V> codec) {
void encode(ByteBuf target) {

if (codec instanceof ToByteBufEncoder) {

ToByteBufEncoder<K, V> toByteBufEncoder = (ToByteBufEncoder<K, V>) codec;
if (toByteBufEncoder.isEstimateExact()) {
target.writeByte('$');

IntegerArgument.writeInteger(target, toByteBufEncoder.estimateSize(val));
target.writeBytes(CRLF);

toByteBufEncoder.encodeValue(val, target);
target.writeBytes(CRLF);
} else {
ByteBuf temporaryBuffer = target.alloc().buffer(toByteBufEncoder.estimateSize(val) + 6);

try {
toByteBufEncoder.encodeValue(val, temporaryBuffer);
ByteBufferArgument.writeByteBuf(target, temporaryBuffer);
} finally {
temporaryBuffer.release();
}
}

CommandArgs.encode(target, (ToByteBufEncoder<V, V>) codec, val, ToByteBufEncoder::encodeValue);
return;
}

Expand All @@ -771,4 +729,33 @@ public String toString() {

}

static <T> void encode(ByteBuf target, ToByteBufEncoder<T, T> encoder, T item, EncodeFunction<T> encodeFunction) {

if (encoder.isEstimateExact()) {

target.writeByte('$');
IntegerArgument.writeInteger(target, encoder.estimateSize(item));
target.writeBytes(CRLF);

encodeFunction.encode(encoder, item, target);
target.writeBytes(CRLF);
} else {

ByteBuf temporaryBuffer = target.alloc().buffer(encoder.estimateSize(item) + 6);

try {
encodeFunction.encode(encoder, item, temporaryBuffer);
ByteBufferArgument.writeByteBuf(target, temporaryBuffer);
} finally {
temporaryBuffer.release();
}
}
}

interface EncodeFunction<T> {

void encode(ToByteBufEncoder<T, T> encoder, T item, ByteBuf target);

}

}

0 comments on commit 6185ebd

Please sign in to comment.