Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve command encoding of singular commands and command batches #212

Closed
cwolfinger opened this issue Mar 15, 2016 · 4 comments
Closed
Labels
type: enhancement A general enhancement
Milestone

Comments

@cwolfinger
Copy link

Hello with certain sized arguments the code always produces a BufferOverflow exception and triggers a buffer resize. The following program illustrates this behavior

    RedisClient client = RedisClient.create(RedisURI.create("localhost", 6379));
    for (int i = 0; i < 2048; i ++)
    {
        client.connect(ByteArrayCodec.INSTANCE).async().rpush("abc".getBytes(), new byte[i]);
    }

When i hits 17 the overflow occurs.

It seems to me there is a bug in the first line of comparison:

if (buffer.remaining() < arg.remaining()) {
int estimate = buffer.remaining() + arg.remaining() + 10;
realloc(max(buffer.capacity() * 2, estimate));
}

    while (true) {
        try {
            ByteBuffer toWrite = arg.duplicate();
            buffer.put((byte) '$');
            write(toWrite.remaining());
            buffer.put(CRLF);
            buffer.put(toWrite);
            buffer.put(CRLF);
            break;
        } catch (BufferOverflowException e) {
            buffer.reset();
            realloc(buffer.capacity() * 2);
        }
    }

It seems that it should be something like this:

if (buffer.remaining() < arg.remaining()+10)

I am not sure all of the combinations this is hit quite a bit ...

@cwolfinger
Copy link
Author

In looking at the code - i think the write block needs to change to:

    private CommandArgs<K, V> write(ByteBuffer arg) {
        buffer.mark();

        if (buffer.remaining() < arg.remaining() + 10) {
            int estimate = buffer.capacity() + arg.remaining() + 10;
            realloc(max(buffer.capacity() * 2, estimate));
        }

This eliminates the exception. It would also be useful to have an option to set the start value for the buffer since in general the calling program has a pretty good idea of the basic size of the command plus value.

@mp911de
Copy link
Collaborator

mp911de commented Mar 16, 2016

Hi @cwolfinger,
thanks for your report. I actually started a couple days ago looking into CommandArgs because the real issue is that itself allocates memory. That's quite costly. When writing a command, the command encoder needs to allocate memory anyways and it's cheaper to allocate memory once.

Btw. there's an issue in your code since you create 2048 connections and you don't close them.

@mp911de mp911de added this to the Lettuce 4.2 milestone Mar 16, 2016
mp911de added a commit that referenced this issue Mar 16, 2016
CommandArgs now does not allocate a byte buffer to write command args as they are added but collects args in a list. Arguments are written to a buffer only when the command encoding is triggered to a buffer that is allocated outside of CommandArgs. This removes the need to know buffer sizes inside of CommandArgs.
@cwolfinger
Copy link
Author

Great - just tested and this seems to get rid of the exceptions. The test code was quick and dirty so not unexpected it leaked connections.

mp911de added a commit that referenced this issue Mar 17, 2016
CommandEncoder takes batch size into account when allocating memory for writing commands. Refactoring of SentTimes tracking. Command latency is stored within the command. Added comand wrapper interface to mark decorated commands.
mp911de added a commit that referenced this issue Mar 17, 2016
Replace LinkedList by own array to implement a stack behavior optimized for the used operations. Use a ByteBufProcessor to parse long values. Add JMH benchmark.
@mp911de
Copy link
Collaborator

mp911de commented Mar 17, 2016

Refactored command encoding, command args and command decoding.

@mp911de mp911de closed this as completed Mar 17, 2016
@mp911de mp911de added the type: enhancement A general enhancement label Mar 17, 2016
@mp911de mp911de changed the title Issue with Exception on Command Write Improve command encoding of singular commands and command batches Jun 1, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants