QpackEncoder.encode should take buffer to encode into instead of allocating.
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
0ccb826532
commit
5cde0ca7c8
|
@ -36,8 +36,6 @@ import org.eclipse.jetty.http3.qpack.internal.parser.EncoderInstructionParser;
|
||||||
import org.eclipse.jetty.http3.qpack.internal.table.DynamicTable;
|
import org.eclipse.jetty.http3.qpack.internal.table.DynamicTable;
|
||||||
import org.eclipse.jetty.http3.qpack.internal.table.Entry;
|
import org.eclipse.jetty.http3.qpack.internal.table.Entry;
|
||||||
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
import org.eclipse.jetty.http3.qpack.internal.util.NBitIntegerEncoder;
|
||||||
import org.eclipse.jetty.io.ByteBufferPool;
|
|
||||||
import org.eclipse.jetty.io.NullByteBufferPool;
|
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.util.component.Dumpable;
|
import org.eclipse.jetty.util.component.Dumpable;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
@ -83,27 +81,19 @@ public class QpackEncoder implements Dumpable
|
||||||
void onInstruction(Instruction instruction) throws QpackException;
|
void onInstruction(Instruction instruction) throws QpackException;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final ByteBufferPool _bufferPool;
|
|
||||||
private final Handler _handler;
|
private final Handler _handler;
|
||||||
private final QpackContext _context;
|
private final QpackContext _context;
|
||||||
private final int _maxBlockedStreams;
|
private final int _maxBlockedStreams;
|
||||||
private final Map<Integer, StreamInfo> _streamInfoMap = new HashMap<>();
|
private final Map<Integer, StreamInfo> _streamInfoMap = new HashMap<>();
|
||||||
private final EncoderInstructionParser _parser;
|
private final EncoderInstructionParser _parser;
|
||||||
private int _knownInsertCount;
|
private int _knownInsertCount = 0;
|
||||||
private int _blockedStreams = 0;
|
private int _blockedStreams = 0;
|
||||||
|
|
||||||
public QpackEncoder(Handler handler, int maxBlockedStreams)
|
public QpackEncoder(Handler handler, int maxBlockedStreams)
|
||||||
{
|
|
||||||
this(handler, maxBlockedStreams, new NullByteBufferPool());
|
|
||||||
}
|
|
||||||
|
|
||||||
public QpackEncoder(Handler handler, int maxBlockedStreams, ByteBufferPool bufferPool)
|
|
||||||
{
|
{
|
||||||
_handler = handler;
|
_handler = handler;
|
||||||
_bufferPool = bufferPool;
|
|
||||||
_context = new QpackContext();
|
_context = new QpackContext();
|
||||||
_maxBlockedStreams = maxBlockedStreams;
|
_maxBlockedStreams = maxBlockedStreams;
|
||||||
_knownInsertCount = 0;
|
|
||||||
_parser = new EncoderInstructionParser(new EncoderAdapter());
|
_parser = new EncoderInstructionParser(new EncoderAdapter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +105,6 @@ public class QpackEncoder implements Dumpable
|
||||||
/**
|
/**
|
||||||
* Set the capacity of the DynamicTable and send a instruction to set the capacity on the remote Decoder.
|
* Set the capacity of the DynamicTable and send a instruction to set the capacity on the remote Decoder.
|
||||||
* @param capacity the new capacity.
|
* @param capacity the new capacity.
|
||||||
* @throws QpackException
|
|
||||||
*/
|
*/
|
||||||
public void setCapacity(int capacity) throws QpackException
|
public void setCapacity(int capacity) throws QpackException
|
||||||
{
|
{
|
||||||
|
@ -180,7 +169,7 @@ public class QpackEncoder implements Dumpable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ByteBuffer encode(int streamId, MetaData metadata) throws QpackException
|
public void encode(ByteBuffer buffer, int streamId, MetaData metadata) throws QpackException
|
||||||
{
|
{
|
||||||
// Verify that we can encode without errors.
|
// Verify that we can encode without errors.
|
||||||
if (metadata.getFields() != null)
|
if (metadata.getFields() != null)
|
||||||
|
@ -234,16 +223,7 @@ public class QpackEncoder implements Dumpable
|
||||||
deltaBase = signBit ? requiredInsertCount - base - 1 : base - requiredInsertCount;
|
deltaBase = signBit ? requiredInsertCount - base - 1 : base - requiredInsertCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the size required. TODO: it may be more efficient to just use a buffer of MAX_HEADER_SIZE?
|
// Encode all the entries into the buffer.
|
||||||
int spaceRequired = 0;
|
|
||||||
spaceRequired += 1 + NBitIntegerEncoder.octectsNeeded(8, encodedInsertCount);
|
|
||||||
spaceRequired += 1 + NBitIntegerEncoder.octectsNeeded(7, deltaBase);
|
|
||||||
for (EncodableEntry encodableEntry : encodableEntries)
|
|
||||||
{
|
|
||||||
spaceRequired += encodableEntry.getRequiredSize(base);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer buffer = _bufferPool.acquire(spaceRequired, false);
|
|
||||||
int pos = BufferUtil.flipToFill(buffer);
|
int pos = BufferUtil.flipToFill(buffer);
|
||||||
|
|
||||||
// Encode the Field Section Prefix into the ByteBuffer.
|
// Encode the Field Section Prefix into the ByteBuffer.
|
||||||
|
@ -258,7 +238,6 @@ public class QpackEncoder implements Dumpable
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferUtil.flipToFlush(buffer, pos);
|
BufferUtil.flipToFlush(buffer, pos);
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private EncodableEntry encode(StreamInfo streamInfo, HttpField field) throws QpackException
|
private EncodableEntry encode(StreamInfo streamInfo, HttpField field) throws QpackException
|
||||||
|
|
|
@ -77,7 +77,8 @@ public class EncodeDecodeTest
|
||||||
int streamId = 0;
|
int streamId = 0;
|
||||||
HttpFields httpFields = HttpFields.build().add(":path", "/index.html");
|
HttpFields httpFields = HttpFields.build().add(":path", "/index.html");
|
||||||
|
|
||||||
ByteBuffer buffer = _encoder.encode(streamId, new MetaData(HttpVersion.HTTP_3, httpFields));
|
ByteBuffer buffer = BufferUtil.allocate(1024);
|
||||||
|
_encoder.encode(buffer, streamId, new MetaData(HttpVersion.HTTP_3, httpFields));
|
||||||
assertNull(_encoderHandler.getInstruction());
|
assertNull(_encoderHandler.getInstruction());
|
||||||
assertThat(BufferUtil.toHexString(buffer), QpackTestUtil.equalsHex("0000 510b 2f69 6e64 6578 2e68 746d 6c"));
|
assertThat(BufferUtil.toHexString(buffer), QpackTestUtil.equalsHex("0000 510b 2f69 6e64 6578 2e68 746d 6c"));
|
||||||
assertTrue(_encoderHandler.isEmpty());
|
assertTrue(_encoderHandler.isEmpty());
|
||||||
|
@ -107,7 +108,7 @@ public class EncodeDecodeTest
|
||||||
httpFields = HttpFields.build()
|
httpFields = HttpFields.build()
|
||||||
.add(":authority", "www.example.com")
|
.add(":authority", "www.example.com")
|
||||||
.add(":path", "/sample/path");
|
.add(":path", "/sample/path");
|
||||||
buffer = _encoder.encode(streamId, new MetaData(HttpVersion.HTTP_3, httpFields));
|
_encoder.encode(buffer, streamId, new MetaData(HttpVersion.HTTP_3, httpFields));
|
||||||
|
|
||||||
instruction = _encoderHandler.getInstruction();
|
instruction = _encoderHandler.getInstruction();
|
||||||
assertThat(instruction, instanceOf(IndexedNameEntryInstruction.class));
|
assertThat(instruction, instanceOf(IndexedNameEntryInstruction.class));
|
||||||
|
|
|
@ -20,6 +20,7 @@ import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpFields;
|
import org.eclipse.jetty.http.HttpFields;
|
||||||
import org.eclipse.jetty.http.HttpVersion;
|
import org.eclipse.jetty.http.HttpVersion;
|
||||||
import org.eclipse.jetty.http.MetaData;
|
import org.eclipse.jetty.http.MetaData;
|
||||||
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
@ -58,12 +59,14 @@ public class EvictionTest
|
||||||
public void test() throws Exception
|
public void test() throws Exception
|
||||||
{
|
{
|
||||||
_encoder.setCapacity(1024);
|
_encoder.setCapacity(1024);
|
||||||
|
ByteBuffer encodedFields = BufferUtil.allocate(1024);
|
||||||
|
|
||||||
for (int i = 0; i < 10000; i++)
|
for (int i = 0; i < 10000; i++)
|
||||||
{
|
{
|
||||||
HttpFields httpFields = newRandomFields(5);
|
HttpFields httpFields = newRandomFields(5);
|
||||||
int streamId = getPositiveInt(10);
|
int streamId = getPositiveInt(10);
|
||||||
ByteBuffer encodedFields = _encoder.encode(streamId, new MetaData(HttpVersion.HTTP_3, httpFields));
|
|
||||||
|
_encoder.encode(encodedFields, streamId, new MetaData(HttpVersion.HTTP_3, httpFields));
|
||||||
_decoder.decode(streamId, encodedFields);
|
_decoder.decode(streamId, encodedFields);
|
||||||
MetaData result = _decoderHandler.getMetaData();
|
MetaData result = _decoderHandler.getMetaData();
|
||||||
|
|
||||||
|
@ -77,6 +80,7 @@ public class EvictionTest
|
||||||
// System.err.println();
|
// System.err.println();
|
||||||
|
|
||||||
assertTrue(result.getFields().isEqualTo(httpFields));
|
assertTrue(result.getFields().isEqualTo(httpFields));
|
||||||
|
BufferUtil.clear(encodedFields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue