Skip to content

Commit

Permalink
Reduce memory usage of QuicheQuicChannel (#653)
Browse files Browse the repository at this point in the history
Motivation:

We might have a lot of QuicheQuicChannel in memory so we should try to
keep the memory usage as low as possible.

Modifications:

Grow long[] for readable streams and writable streams dynamically

Result:

Less memory usage when not a lot of streams are active
  • Loading branch information
normanmaurer committed Feb 3, 2024
1 parent 3427098 commit 41a7537
Showing 1 changed file with 25 additions and 2 deletions.
Expand Up @@ -118,8 +118,8 @@ public void operationComplete(ChannelFuture channelFuture) {
};

private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
private final long[] readableStreams = new long[128];
private final long[] writableStreams = new long[128];
private long[] readableStreams = new long[4];
private long[] writableStreams = new long[4];

private final LongObjectMap<QuicheQuicStreamChannel> streams = new LongObjectHashMap<>();
private final QuicheQuicChannelConfig config;
Expand Down Expand Up @@ -220,6 +220,19 @@ static QuicheQuicChannel forServer(Channel parent, ByteBuffer key, InetSocketAdd
sslTaskExecutor);
}

private static final int MAX_ARRAY_LEN = 128;

private static long[] growIfNeeded(long[] array, int maxLength) {
if (maxLength > array.length) {
if (array.length == MAX_ARRAY_LEN) {
return array;
}
// Increase by 4 until we reach MAX_ARRAY_LEN
return new long[Math.min(MAX_ARRAY_LEN, array.length + 4)];
}
return array;
}

@Override
public boolean isTimedOut() {
return timedOut;
Expand Down Expand Up @@ -979,6 +992,7 @@ private boolean handleWritableStreams() {
Quiche.quiche_conn_is_in_early_data(connAddr)) {
long writableIterator = Quiche.quiche_conn_writable(connAddr);

int totalWritable = 0;
try {
// For streams we always process all streams when at least on read was requested.
for (;;) {
Expand All @@ -997,6 +1011,9 @@ private boolean handleWritableStreams() {
}
}
}
if (writable > 0) {
totalWritable += writable;
}
if (writable < writableStreams.length) {
// We did handle all writable streams.
break;
Expand All @@ -1005,6 +1022,7 @@ private boolean handleWritableStreams() {
} finally {
Quiche.quiche_stream_iter_free(writableIterator);
}
writableStreams = growIfNeeded(writableStreams, totalWritable);
}
return mayNeedWrite;
} finally {
Expand Down Expand Up @@ -1674,6 +1692,7 @@ void recv() {
private void recvStream() {
long connAddr = connection.address();
long readableIterator = Quiche.quiche_conn_readable(connAddr);
int totalReadable = 0;
if (readableIterator != -1) {
try {
// For streams we always process all streams when at least on read was requested.
Expand All @@ -1699,11 +1718,15 @@ private void recvStream() {
streamReadable = false;
break;
}
if (readable > 0) {
totalReadable += readable;
}
}
}
} finally {
Quiche.quiche_stream_iter_free(readableIterator);
}
readableStreams = growIfNeeded(readableStreams, totalReadable);
}
}

Expand Down

0 comments on commit 41a7537

Please sign in to comment.