Optimize length-reading of HttpDecoder.
Use fixed-size array as buffer and only buffer when necessary.
gfe-relnote: n/a --under version 99, which isn't used in production.
PiperOrigin-RevId: 244911379
Change-Id: I8b24f09b0b13be33b5f35fc12e42b5fae73d186b
diff --git a/quic/core/http/http_decoder.cc b/quic/core/http/http_decoder.cc
index e0c7383..c59e8b0 100644
--- a/quic/core/http/http_decoder.cc
+++ b/quic/core/http/http_decoder.cc
@@ -35,7 +35,7 @@
: visitor_(nullptr),
state_(STATE_READING_FRAME_TYPE),
current_frame_type_(0),
- current_length_field_size_(0),
+ current_length_field_length_(0),
remaining_length_field_length_(0),
current_frame_length_(0),
remaining_frame_length_(0),
@@ -119,16 +119,41 @@
void HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
DCHECK_NE(0u, reader->BytesRemaining());
- BufferFrameLength(reader);
- if (remaining_length_field_length_ != 0) {
- return;
- }
- QuicDataReader length_reader(length_buffer_.data(),
- current_length_field_size_);
- if (!length_reader.ReadVarInt62(¤t_frame_length_)) {
- RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
- visitor_->OnError(this);
- return;
+ if (current_length_field_length_ == 0) {
+ // A new frame is coming.
+ current_length_field_length_ = reader->PeekVarInt62Length();
+ if (current_length_field_length_ == 0) {
+ RaiseError(QUIC_INTERNAL_ERROR,
+ "Unable to read the length of frame length");
+ visitor_->OnError(this);
+ return;
+ }
+ if (current_length_field_length_ <= reader->BytesRemaining()) {
+ // The reader has all length data needed, so no need to buffer.
+ if (!reader->ReadVarInt62(¤t_frame_length_)) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
+ return;
+ }
+ } else {
+ // Buffer a new length field.
+ remaining_length_field_length_ = current_length_field_length_;
+ BufferFrameLength(reader);
+ return;
+ }
+ } else {
+ // Buffer the existing length field.
+ BufferFrameLength(reader);
+ // The frame is still not buffered completely.
+ if (remaining_length_field_length_ != 0) {
+ return;
+ }
+ QuicDataReader length_reader(length_buffer_.data(),
+ current_length_field_length_);
+ if (!length_reader.ReadVarInt62(¤t_frame_length_)) {
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to read buffered frame length");
+ visitor_->OnError(this);
+ return;
+ }
}
if (current_frame_length_ > MaxFrameLength(current_frame_type_)) {
@@ -141,15 +166,15 @@
// frame payload.
if (current_frame_type_ == 0x0) {
visitor_->OnDataFrameStart(Http3FrameLengths(
- current_length_field_size_ + current_type_field_length_,
+ current_length_field_length_ + current_type_field_length_,
current_frame_length_));
} else if (current_frame_type_ == 0x1) {
visitor_->OnHeadersFrameStart(Http3FrameLengths(
- current_length_field_size_ + current_type_field_length_,
+ current_length_field_length_ + current_type_field_length_,
current_frame_length_));
} else if (current_frame_type_ == 0x4) {
visitor_->OnSettingsFrameStart(Http3FrameLengths(
- current_length_field_size_ + current_type_field_length_,
+ current_length_field_length_ + current_type_field_length_,
current_frame_length_));
}
@@ -360,7 +385,7 @@
}
}
- current_length_field_size_ = 0;
+ current_length_field_length_ = 0;
current_type_field_length_ = 0;
state_ = STATE_READING_FRAME_TYPE;
}
@@ -376,7 +401,7 @@
remaining_frame_length_ -= payload.length();
if (remaining_frame_length_ == 0) {
state_ = STATE_READING_FRAME_TYPE;
- current_length_field_size_ = 0;
+ current_length_field_length_ = 0;
current_type_field_length_ = 0;
}
}
@@ -398,25 +423,15 @@
}
void HttpDecoder::BufferFrameLength(QuicDataReader* reader) {
- if (current_length_field_size_ == 0) {
- current_length_field_size_ = reader->PeekVarInt62Length();
- if (current_length_field_size_ == 0) {
- RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
- visitor_->OnError(this);
- return;
- }
- remaining_length_field_length_ = current_length_field_size_;
- }
- if (current_length_field_size_ == remaining_length_field_length_) {
- length_buffer_.erase(length_buffer_.size());
- length_buffer_.reserve(current_length_field_size_);
+ if (current_length_field_length_ == remaining_length_field_length_) {
+ length_buffer_.fill(0);
}
QuicByteCount bytes_to_read = std::min<QuicByteCount>(
remaining_length_field_length_, reader->BytesRemaining());
- if (!reader->ReadBytes(&(length_buffer_[0]) + current_length_field_size_ -
+ if (!reader->ReadBytes(length_buffer_.data() + current_length_field_length_ -
remaining_length_field_length_,
bytes_to_read)) {
- RaiseError(QUIC_INTERNAL_ERROR, "Unable to read frame length");
+ RaiseError(QUIC_INTERNAL_ERROR, "Unable to buffer frame length bytes.");
visitor_->OnError(this);
return;
}