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.