Take into account remainder due to integer division when calculating cycle

This commit is contained in:
Tatsuhiro Tsujikawa 2015-12-08 23:15:55 +09:00
parent 4bcc14fc67
commit abcdbf0039
2 changed files with 35 additions and 20 deletions

View File

@ -80,6 +80,7 @@ void nghttp2_stream_init(nghttp2_stream *stream, int32_t stream_id,
stream->queued = 0; stream->queued = 0;
stream->descendant_last_cycle = 0; stream->descendant_last_cycle = 0;
stream->cycle = 0; stream->cycle = 0;
stream->pending_penalty = 0;
stream->descendant_next_seq = 0; stream->descendant_next_seq = 0;
stream->seq = 0; stream->seq = 0;
stream->last_writelen = 0; stream->last_writelen = 0;
@ -115,9 +116,14 @@ static int stream_subtree_active(nghttp2_stream *stream) {
/* /*
* Returns next cycle for |stream|. * Returns next cycle for |stream|.
*/ */
static uint64_t stream_next_cycle(nghttp2_stream *stream, uint64_t last_cycle) { static void stream_next_cycle(nghttp2_stream *stream, uint64_t last_cycle) {
return last_cycle + size_t penalty;
stream->last_writelen * NGHTTP2_MAX_WEIGHT / (uint32_t)stream->weight;
penalty =
stream->last_writelen * NGHTTP2_MAX_WEIGHT + stream->pending_penalty;
stream->cycle = last_cycle + penalty / (uint32_t)stream->weight;
stream->pending_penalty = penalty % (uint32_t)stream->weight;
} }
static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) { static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
@ -125,8 +131,7 @@ static int stream_obq_push(nghttp2_stream *dep_stream, nghttp2_stream *stream) {
for (; dep_stream && !stream->queued; for (; dep_stream && !stream->queued;
stream = dep_stream, dep_stream = dep_stream->dep_prev) { stream = dep_stream, dep_stream = dep_stream->dep_prev) {
stream->cycle = stream_next_cycle(stream, dep_stream->descendant_last_cycle);
stream_next_cycle(stream, dep_stream->descendant_last_cycle);
stream->seq = dep_stream->descendant_next_seq++; stream->seq = dep_stream->descendant_next_seq++;
DEBUGF(fprintf(stderr, "stream: stream=%d obq push cycle=%ld\n", DEBUGF(fprintf(stderr, "stream: stream=%d obq push cycle=%ld\n",
@ -169,6 +174,7 @@ static void stream_obq_remove(nghttp2_stream *stream) {
stream->queued = 0; stream->queued = 0;
stream->cycle = 0; stream->cycle = 0;
stream->pending_penalty = 0;
stream->descendant_last_cycle = 0; stream->descendant_last_cycle = 0;
stream->last_writelen = 0; stream->last_writelen = 0;
@ -209,8 +215,7 @@ void nghttp2_stream_reschedule(nghttp2_stream *stream) {
for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) { for (; dep_stream; stream = dep_stream, dep_stream = dep_stream->dep_prev) {
nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry); nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
stream->cycle = stream_next_cycle(stream, dep_stream->descendant_last_cycle);
stream_next_cycle(stream, dep_stream->descendant_last_cycle);
stream->seq = dep_stream->descendant_next_seq++; stream->seq = dep_stream->descendant_next_seq++;
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);
@ -225,8 +230,8 @@ void nghttp2_stream_reschedule(nghttp2_stream *stream) {
void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) { void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
nghttp2_stream *dep_stream; nghttp2_stream *dep_stream;
uint64_t last_cycle; uint64_t last_cycle;
uint64_t cycle;
int32_t old_weight; int32_t old_weight;
size_t wlen_penalty;
if (stream->weight == weight) { if (stream->weight == weight) {
return; return;
@ -247,20 +252,28 @@ void nghttp2_stream_change_weight(nghttp2_stream *stream, int32_t weight) {
return; 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); nghttp2_pq_remove(&dep_stream->obq, &stream->pq_entry);
stream->cycle = cycle; wlen_penalty = stream->last_writelen * NGHTTP2_MAX_WEIGHT;
stream->seq = dep_stream->descendant_next_seq++;
/* Compute old stream->pending_penalty we used to calculate
stream->cycle */
stream->pending_penalty = (stream->pending_penalty + (uint32_t)old_weight -
(wlen_penalty % (uint32_t)old_weight)) %
(uint32_t)old_weight;
last_cycle = stream->cycle -
(wlen_penalty + stream->pending_penalty) / (uint32_t)old_weight;
/* Now we have old stream->pending_penalty and new stream->weight in
place */
stream_next_cycle(stream, last_cycle);
if (stream->cycle < dep_stream->descendant_last_cycle) {
stream->cycle = dep_stream->descendant_last_cycle;
}
/* Continue to use same stream->seq */
nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry); nghttp2_pq_push(&dep_stream->obq, &stream->pq_entry);

View File

@ -197,6 +197,8 @@ struct nghttp2_stream {
int32_t local_window_size; int32_t local_window_size;
/* weight of this stream */ /* weight of this stream */
int32_t weight; int32_t weight;
/* This is unpaid penalty (offset) when calculating cycle. */
uint32_t pending_penalty;
/* sum of weight of direct descendants */ /* sum of weight of direct descendants */
int32_t sum_dep_weight; int32_t sum_dep_weight;
nghttp2_stream_state state; nghttp2_stream_state state;