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.
This commit is contained in:
Tatsuhiro Tsujikawa 2015-12-07 23:08:54 +09:00
parent 72f815d535
commit 4bcc14fc67
3 changed files with 55 additions and 9 deletions

View File

@ -666,15 +666,9 @@ int nghttp2_session_reprioritize_stream(
assert(dep_stream); assert(dep_stream);
if (dep_stream == stream->dep_prev && !pri_spec->exclusive) { if (dep_stream == stream->dep_prev && !pri_spec->exclusive) {
/* This is minor optimization when just weight is changed. /* This is minor optimization when just weight is changed. */
Currently, we don't reschedule stream in this case, since we nghttp2_stream_change_weight(stream, pri_spec->weight);
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;
return 0; return 0;
} }

View File

@ -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) { static nghttp2_stream *stream_last_sib(nghttp2_stream *stream) {
for (; stream->sib_next; stream = stream->sib_next) for (; stream->sib_next; stream = stream->sib_next)
; ;

View File

@ -418,6 +418,12 @@ int nghttp2_stream_in_dep_tree(nghttp2_stream *stream);
*/ */
void nghttp2_stream_reschedule(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 * Returns a stream which has highest priority, updating
* descendant_last_cycle of selected stream's ancestors. * descendant_last_cycle of selected stream's ancestors.