From 4bcc14fc67e668140ac977154c1960b78378e2f9 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 7 Dec 2015 23:08:54 +0900 Subject: [PATCH] Reschedule stream when only weight is changed Previously, we only updated stream's weight field when only weight was changed by PRIORITY frame. If stream is queued, it would be better to actually reschedule it based on new weight. This could be especially useful if weight is increased. --- lib/nghttp2_session.c | 12 +++-------- lib/nghttp2_stream.c | 46 +++++++++++++++++++++++++++++++++++++++++++ lib/nghttp2_stream.h | 6 ++++++ 3 files changed, 55 insertions(+), 9 deletions(-) diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 191e2720..a9829048 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -666,15 +666,9 @@ int nghttp2_session_reprioritize_stream( assert(dep_stream); if (dep_stream == stream->dep_prev && !pri_spec->exclusive) { - /* This is minor optimization when just weight is changed. - Currently, we don't reschedule stream in this case, since we - don't retain enough information to do that - (descendant_last_cycle we used to schedule it). This means new - weight is only applied in the next scheduling, and if weight is - drastically increased, library is not responding very quickly. - If this is really an issue, we will do workaround for this. */ - dep_stream->sum_dep_weight += pri_spec->weight - stream->weight; - stream->weight = pri_spec->weight; + /* This is minor optimization when just weight is changed. */ + nghttp2_stream_change_weight(stream, pri_spec->weight); + return 0; } diff --git a/lib/nghttp2_stream.c b/lib/nghttp2_stream.c index 06b64850..e3280d43 100644 --- a/lib/nghttp2_stream.c +++ b/lib/nghttp2_stream.c @@ -222,6 +222,52 @@ void nghttp2_stream_reschedule(nghttp2_stream *stream) { } } +void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) { + nghttp2_stream *dep_stream; + uint64_t last_cycle; + uint64_t cycle; + int32_t old_weight; + + if (stream->weight == weight) { + return; + } + + old_weight = stream->weight; + stream->weight = weight; + + dep_stream = stream->dep_prev; + + if (!dep_stream) { + return; + } + + dep_stream->sum_dep_weight += weight - old_weight; + + if (!stream->queued) { + return; + } + + last_cycle = + stream->cycle - + stream->last_writelen * NGHTTP2_MAX_WEIGHT / (uint32_t)old_weight; + + cycle = stream_next_cycle(stream, last_cycle); + + if (cycle < dep_stream->descendant_last_cycle) { + cycle = dep_stream->descendant_last_cycle; + } + + nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry); + + stream->cycle = cycle; + stream->seq = dep_stream->descendant_next_seq++; + + nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); + + DEBUGF(fprintf(stderr, "stream: stream=%d obq resched cycle=%ld\n", + stream->stream_id, stream->cycle)); +} + static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) { for (; stream->sib_next; stream = stream->sib_next) ; diff --git a/lib/nghttp2_stream.h b/lib/nghttp2_stream.h index bbb8b9f3..123ea2f2 100644 --- a/lib/nghttp2_stream.h +++ b/lib/nghttp2_stream.h @@ -418,6 +418,12 @@ int nghttp2_stream_in_dep_tree(nghttp2_stream *stream); */ void nghttp2_stream_reschedule(nghttp2_stream *stream); +/* + * Changes |stream|'s weight to |weight|. If |stream| is queued, it + * will be rescheduled based on new weight. + */ +void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight); + /* * Returns a stream which has highest priority, updating * descendant_last_cycle of selected stream's ancestors.