Use absl::Span-based version WriteBodySlices() in GFE. This should not change any functional behavior; however, this does add an extra copy and potentially an extra allocation of a memslice vector. Protected by FLAGS_quic_restart_flag_quic_use_new_mem_slice_span. PiperOrigin-RevId: 378499167
diff --git a/quic/core/http/quic_spdy_stream.cc b/quic/core/http/quic_spdy_stream.cc index 0ef85dc..0c08938 100644 --- a/quic/core/http/quic_spdy_stream.cc +++ b/quic/core/http/quic_spdy_stream.cc
@@ -454,6 +454,24 @@ return WriteMemSlices(slices, fin); } +QuicConsumedData QuicSpdyStream::WriteBodySlices( + absl::Span<QuicMemSlice> slices, + bool fin) { + if (!VersionUsesHttp3(transport_version()) || slices.empty()) { + return WriteMemSlices(slices, fin); + } + + QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection()); + const QuicByteCount data_size = MemSliceSpanTotalSize(slices); + if (!WriteDataFrameHeader(data_size, /*force_write=*/false)) { + return {0, false}; + } + + QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id() + << " is writing DATA frame payload of length " << data_size; + return WriteMemSlices(slices, fin); +} + size_t QuicSpdyStream::Readv(const struct iovec* iov, size_t iov_len) { QUICHE_DCHECK(FinishedReadingHeaders()); if (!VersionUsesHttp3(transport_version())) {
diff --git a/quic/core/http/quic_spdy_stream.h b/quic/core/http/quic_spdy_stream.h index 160ed56..4f962ce 100644 --- a/quic/core/http/quic_spdy_stream.h +++ b/quic/core/http/quic_spdy_stream.h
@@ -18,6 +18,7 @@ #include "absl/base/attributes.h" #include "absl/strings/string_view.h" +#include "absl/types/span.h" #include "quic/core/http/http_decoder.h" #include "quic/core/http/http_encoder.h" #include "quic/core/http/quic_header_list.h" @@ -159,6 +160,7 @@ // Does the same thing as WriteOrBufferBody except this method takes // memslicespan as the data input. Right now it only calls WriteMemSlices. QuicConsumedData WriteBodySlices(QuicMemSliceSpan slices, bool fin); + QuicConsumedData WriteBodySlices(absl::Span<QuicMemSlice> slices, bool fin); // Marks the trailers as consumed. This applies to the case where this object // receives headers and trailers as QuicHeaderLists via calls to
diff --git a/quic/core/quic_utils.cc b/quic/core/quic_utils.cc index b34506c..65c9ced 100644 --- a/quic/core/quic_utils.cc +++ b/quic/core/quic_utils.cc
@@ -21,6 +21,7 @@ #include "quic/platform/api/quic_bug_tracker.h" #include "quic/platform/api/quic_flag_utils.h" #include "quic/platform/api/quic_flags.h" +#include "quic/platform/api/quic_mem_slice.h" #include "common/platform/api/quiche_logging.h" #include "common/platform/api/quiche_prefetch.h" #include "common/quiche_endian.h" @@ -714,5 +715,13 @@ QuicUtils::IsClientInitiatedStreamId(version.transport_version, id); } +QuicByteCount MemSliceSpanTotalSize(absl::Span<QuicMemSlice> span) { + QuicByteCount total = 0; + for (const QuicMemSlice& slice : span) { + total += slice.length(); + } + return total; +} + #undef RETURN_STRING_LITERAL // undef for jumbo builds } // namespace quic
diff --git a/quic/core/quic_utils.h b/quic/core/quic_utils.h index 8530954..6fcc5f2 100644 --- a/quic/core/quic_utils.h +++ b/quic/core/quic_utils.h
@@ -13,6 +13,7 @@ #include "absl/numeric/int128.h" #include "absl/strings/string_view.h" +#include "absl/types/span.h" #include "quic/core/crypto/quic_random.h" #include "quic/core/frames/quic_frame.h" #include "quic/core/quic_connection_id.h" @@ -21,6 +22,7 @@ #include "quic/core/quic_versions.h" #include "quic/platform/api/quic_export.h" #include "quic/platform/api/quic_iovec.h" +#include "quic/platform/api/quic_mem_slice.h" #include "quic/platform/api/quic_socket_address.h" namespace quic { @@ -249,6 +251,8 @@ bool IsValidWebTransportSessionId(WebTransportSessionId id, ParsedQuicVersion transport_version); +QuicByteCount MemSliceSpanTotalSize(absl::Span<QuicMemSlice> span); + template <typename Mask> class QUIC_EXPORT_PRIVATE BitMask { public: