Add minimal spdy priority set by gws response header for initial cwnd bootstrapping for http2. also store spdy priority within spdydispatcher::sessiondata. no production behavior change unless we start an additional gws experiment. protected by gfe2_restart_flag_h2_adjust_initial_cwnd_by_gws.
While QUIC stores SPDY within spdy::PriorityWriteScheduler<...>, SPDY priority is stored in a map from stream_id to SessionData owned by SpdyClientDispatcher in this change because
(1) H2 uses LIFOWriteScheduler<...> by default, which ignores precedence (http://shortn/_2Ny3X9xBh6).
(2) We only need CWND bootstrapping for traffic from client, and hence only SpdyClientDispatcher populates the SPDY priority.
PiperOrigin-RevId: 316117083
Change-Id: I232e421b16edecc5f7146ce4fb36592a71a7e86f
diff --git a/spdy/core/fifo_write_scheduler.h b/spdy/core/fifo_write_scheduler.h
index a2c6989..7b31891 100644
--- a/spdy/core/fifo_write_scheduler.h
+++ b/spdy/core/fifo_write_scheduler.h
@@ -29,6 +29,8 @@
const StreamPrecedenceType& precedence) override;
void UnregisterStream(StreamIdType stream_id) override;
bool StreamRegistered(StreamIdType stream_id) const override;
+ // Stream precedence is available but note that it is not used for scheduling
+ // in this scheduler.
StreamPrecedenceType GetStreamPrecedence(
StreamIdType stream_id) const override;
void UpdateStreamPrecedence(StreamIdType stream_id,
@@ -51,20 +53,26 @@
std::string DebugString() const override;
private:
+ struct StreamInfo {
+ SpdyPriority priority;
+ int64_t event_time; // read/write event time (us since Unix epoch).
+ };
+
std::set<StreamIdType> ready_streams_;
- // This map maps stream ID to read/write event time (us since Unix epoch).
- std::map<StreamIdType, int64_t> registered_streams_;
+ std::map<StreamIdType, StreamInfo> registered_streams_;
};
template <typename StreamIdType>
void FifoWriteScheduler<StreamIdType>::RegisterStream(
StreamIdType stream_id,
- const StreamPrecedenceType& /*precedence*/) {
+ const StreamPrecedenceType& precedence) {
if (StreamRegistered(stream_id)) {
SPDY_BUG << "Stream " << stream_id << " already registered";
return;
}
- registered_streams_.emplace_hint(registered_streams_.end(), stream_id, 0);
+ registered_streams_.emplace_hint(
+ registered_streams_.end(), stream_id,
+ StreamInfo{/*priority=*/precedence.spdy3_priority(), /*event_time=*/0});
}
template <typename StreamIdType>
@@ -88,14 +96,26 @@
template <typename StreamIdType>
typename FifoWriteScheduler<StreamIdType>::StreamPrecedenceType
FifoWriteScheduler<StreamIdType>::GetStreamPrecedence(
- StreamIdType /*stream_id*/) const {
- return StreamPrecedenceType(kV3LowestPriority);
+ StreamIdType stream_id) const {
+ auto it = registered_streams_.find(stream_id);
+ if (it == registered_streams_.end()) {
+ SPDY_DVLOG(1) << "Stream " << stream_id << " not registered";
+ return StreamPrecedenceType(kV3LowestPriority);
+ }
+ return StreamPrecedenceType(it->second.priority);
}
template <typename StreamIdType>
void FifoWriteScheduler<StreamIdType>::UpdateStreamPrecedence(
- StreamIdType /*stream_id*/,
- const StreamPrecedenceType& /*precedence*/) {}
+ StreamIdType stream_id,
+ const StreamPrecedenceType& precedence) {
+ auto it = registered_streams_.find(stream_id);
+ if (it == registered_streams_.end()) {
+ SPDY_DVLOG(1) << "Stream " << stream_id << " not registered";
+ return;
+ }
+ it->second.priority = precedence.spdy3_priority();
+}
template <typename StreamIdType>
std::vector<StreamIdType> FifoWriteScheduler<StreamIdType>::GetStreamChildren(
@@ -109,7 +129,7 @@
int64_t now_in_usec) {
auto it = registered_streams_.find(stream_id);
if (it != registered_streams_.end()) {
- it->second = now_in_usec;
+ it->second.event_time = now_in_usec;
} else {
SPDY_BUG << "Stream " << stream_id << " is not registered";
}
@@ -128,7 +148,8 @@
if (stream_id <= it->first) {
break;
}
- latest_event_time_us = std::max(latest_event_time_us, it->second);
+ latest_event_time_us =
+ std::max(latest_event_time_us, it->second.event_time);
}
return latest_event_time_us;
}