From 162a90066020a6086d1f5fc9f54d288b99892462 Mon Sep 17 00:00:00 2001 From: irungentoo Date: Sat, 16 Aug 2014 18:14:47 -0400 Subject: [PATCH] New congestion control algorithm. This new congestion control algorithm uses the increase in size of the send queue to regulate how fast it sends data. When tweaked it should work better than the old one. --- toxcore/net_crypto.c | 103 +++++++++---------------------------------- toxcore/net_crypto.h | 11 ++--- 2 files changed, 28 insertions(+), 86 deletions(-) diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 463b7356..5b89f69c 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -2300,95 +2300,42 @@ static void send_crypto_packets(Net_Crypto *c) conn->packet_counter = 0; conn->packet_counter_set = temp_time; + double real_send_rate = (double)(conn->packets_sent + conn->packets_resent) / (dt / 1000.0); + uint32_t packets_sent = conn->packets_sent; + conn->packets_sent = conn->packets_resent = 0; + /* conjestion control calculate a new value of conn->packet_send_rate based on some data notes: needs improvement but seems to work fine for packet loss <1% */ - /* additional step: adjust the send rate based on the size change of the send queue */ - uint32_t queue_size = num_packets_array(&conn->send_array); + unsigned int pos = conn->last_sendqueue_counter % CONGESTION_QUEUE_ARRAY_SIZE; + conn->last_sendqueue_size[pos] = num_packets_array(&conn->send_array); + ++conn->last_sendqueue_counter; - if (queue_size > conn->packet_send_rate && queue_size > conn->last_queue_size) { - conn->rate_increase = 0; - conn->packets_resent = conn->packets_sent; + unsigned int j; + long signed int sum = 0; + sum = (long signed int)conn->last_sendqueue_size[(pos) % CONGESTION_QUEUE_ARRAY_SIZE] - + (long signed int)conn->last_sendqueue_size[(pos - (CONGESTION_QUEUE_ARRAY_SIZE - 1)) % CONGESTION_QUEUE_ARRAY_SIZE]; + + conn->last_num_packets_sent[pos] = packets_sent; + long signed int total_sent = 0; + + for (j = 0; j < CONGESTION_QUEUE_ARRAY_SIZE; ++j) { + total_sent += conn->last_num_packets_sent[j]; } + total_sent -= sum; - //hack to prevent 1 packet lost from affecting calculations at low send rates - if (conn->packets_resent == 1) { - conn->packets_resent = 0; - } + double min_speed = 1000.0 * (((double)(total_sent)) / ((double)(CONGESTION_QUEUE_ARRAY_SIZE) * + PACKET_COUNTER_AVERAGE_INTERVAL)); - //new "dropped" value: weighted average of previous value and packet drop rate measured by the number of packets which were resends of previous packets - double dropped = (conn->dropped) * 0.30 + ((double)conn->packets_resent / dt) * 0.70; - - //since the "dropped" packets measure is delayed in time from the actual # of dropped packets, - // ignore dropped packet measure for 2 seconds after it becomes high and the send rate is lowered as a result - double drop_ignore_new; - - if (conn->drop_ignore_start + 2000 < temp_time) { - drop_ignore_new = 0.0; - - if ((dropped * 1000.0) / conn->packet_send_rate >= 0.10) { - conn->drop_ignore_start = temp_time; - } - } else { - drop_ignore_new = (dropped > conn->drop_ignore) ? dropped : conn->drop_ignore; - } - - //calculate the "real" send rate (send rate - drop rate) - double r = conn->packet_send_rate; - double realrate = (r - (dropped - drop_ignore_new) * 1000.0); - - if (dropped < drop_ignore_new) { - realrate = r; - } - - //calculate exponential increase in rate, triggered when drop rate is below 5% for 5 seconds - if ((dropped * 1000.0) / conn->packet_send_rate >= 0.05) { - conn->rate_increase_stop_start = temp_time; - } - - if (conn->rate_increase_stop_start + 5000 < temp_time) { - if (conn->rate_increase < 1.0) { - conn->rate_increase = 1.0; - } - - conn->rate_increase *= pow(1.1, pow(realrate / r, 10.0));; - } else { - conn->rate_increase = 0.0; - } - - - //"constant" linear increase in rate - double linear_increase = realrate * 0.0025 + 1.0; - - //final send rate: average of "real" and previous send rates + increases - double newrate = (realrate + conn->packet_send_rate) / 2.0 + conn->rate_increase + linear_increase; - conn->last_send_rate = conn->packet_send_rate; - conn->packet_send_rate = newrate; - - - conn->dropped = dropped; - conn->drop_ignore = drop_ignore_new; - conn->packets_resent = 0; - conn->last_queue_size = queue_size; - - if (!conn->sending || !conn->packets_sent) { - conn->rate_increase = 0; - conn->packet_send_rate /= 2; - } + conn->packet_send_rate = min_speed * 1.3; if (conn->packet_send_rate < CRYPTO_PACKET_MIN_RATE) { conn->packet_send_rate = CRYPTO_PACKET_MIN_RATE; } - conn->packets_sent = 0; - - if (conn->sending != 0 && num_packets_array(&conn->send_array) < CRYPTO_MIN_QUEUE_LENGTH / 2) { - --conn->sending; - } - } if (conn->last_packets_left_set == 0) { @@ -2409,13 +2356,8 @@ static void send_crypto_packets(Net_Crypto *c) int ret = send_requested_packets(c, i, conn->packets_left); if (ret != -1) { - if (ret != 0) { - conn->sending = CONN_SENDING_VALUE; - } - - conn->packets_resent += ret; conn->packets_left -= ret; - conn->packets_sent += ret; + conn->packets_resent += ret; } if (conn->packet_send_rate > CRYPTO_PACKET_MIN_RATE * 1.5) { @@ -2496,7 +2438,6 @@ int64_t write_cryptpacket(const Net_Crypto *c, int crypt_connection_id, const ui --conn->packets_left; conn->packets_sent++; - conn->sending = CONN_SENDING_VALUE; return ret; } diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 2918dd44..b931d1db 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -79,6 +79,9 @@ #define CRYPTO_MAX_PADDING 8 /* All packets will be padded a number of bytes based on this number. */ + +#define CONGESTION_QUEUE_ARRAY_SIZE 8 + typedef struct { uint64_t time; uint16_t length; @@ -143,11 +146,9 @@ typedef struct { uint32_t packets_left; uint64_t last_packets_left_set; - double dropped, drop_ignore, rate_increase, last_send_rate; - uint64_t drop_ignore_start, rate_increase_stop_start; - uint32_t packets_resent, last_queue_size, packets_sent, last_packets_sent; - - uint8_t sending; /* indicates if data is being sent or not. */ + uint32_t last_sendqueue_size[CONGESTION_QUEUE_ARRAY_SIZE], last_sendqueue_counter; + long signed int last_num_packets_sent[CONGESTION_QUEUE_ARRAY_SIZE]; + uint32_t packets_sent, packets_resent; uint8_t killed; /* set to 1 to kill the connection. */