forked from premiere/premiere-libtorrent
instead of using a fixed request timeout for every peer, have an adaptable one based on the average download time for a block
This commit is contained in:
parent
c4e5df8e4d
commit
4eaec6d87f
|
@ -474,10 +474,16 @@ void print_peer_info(std::string& out, std::vector<libtorrent::peer_info> const&
|
|||
}
|
||||
if (print_timers)
|
||||
{
|
||||
snprintf(str, sizeof(str), "%8d %4d %7d %6d "
|
||||
char req_timeout[20] = "-";
|
||||
// timeout is only meaningful if there is at least one outstanding
|
||||
// request to the peer
|
||||
if (i->download_queue_length > 0)
|
||||
snprintf(req_timeout, sizeof(req_timeout), "%d", i->request_timeout);
|
||||
|
||||
snprintf(str, sizeof(str), "%8d %4d %7s %6d "
|
||||
, int(total_seconds(i->last_active))
|
||||
, int(total_seconds(i->last_request))
|
||||
, i->request_timeout
|
||||
, req_timeout
|
||||
, int(total_seconds(i->download_queue_time)));
|
||||
out += str;
|
||||
}
|
||||
|
|
|
@ -108,23 +108,18 @@ namespace libtorrent
|
|||
{
|
||||
pending_block(piece_block const& b)
|
||||
: block(b), send_buffer_offset(-1), not_wanted(false)
|
||||
, timed_out(false), busy(false), receiving(false)
|
||||
, timed_out(false), busy(false)
|
||||
{}
|
||||
|
||||
piece_block block;
|
||||
|
||||
// the time we sent this request. This is used to track the round-trip
|
||||
// time of receiving the piece. This is not initialized until this
|
||||
// pending_block is inserted in the download queue (i.e. not the
|
||||
// requst_queue)
|
||||
ptime request_time;
|
||||
|
||||
// the number of bytes into the send buffer this request is. Every time
|
||||
// some portion of the send buffer is transmitted, this offset is
|
||||
// decremented by the number of bytes sent. once this drops below 0, the
|
||||
// request_time field is set to the current time.
|
||||
// if the request has not been written to the send buffer, this field
|
||||
// remoains -1.
|
||||
// remains -1.
|
||||
// TODO: 3 make this 29 bits, to fit the bools in its tail
|
||||
int send_buffer_offset;
|
||||
|
||||
// if any of these are set to true, this block
|
||||
|
@ -142,11 +137,6 @@ namespace libtorrent
|
|||
// busy request at a time in each peer's queue
|
||||
bool busy:1;
|
||||
|
||||
// this is true when we first start to receive the resopnse for this
|
||||
// request. The first time we read the message header for the piece
|
||||
// response is when we calculate the RTT for this request.
|
||||
bool receiving:1;
|
||||
|
||||
bool operator==(pending_block const& b)
|
||||
{
|
||||
return b.block == block
|
||||
|
@ -831,6 +821,7 @@ namespace libtorrent
|
|||
void on_disk_write_complete(disk_io_job const* j
|
||||
, peer_request r, boost::shared_ptr<torrent> t);
|
||||
void on_seed_mode_hashed(disk_io_job const* j);
|
||||
int request_timeout() const;
|
||||
|
||||
int wanted_transfer(int channel);
|
||||
int request_bandwidth(int channel, int bytes = 0);
|
||||
|
@ -914,9 +905,11 @@ namespace libtorrent
|
|||
sliding_average<20> m_piece_rate;
|
||||
sliding_average<20> m_send_rate;
|
||||
|
||||
// the round-trip time of piece requests and the corresponding piece
|
||||
// message
|
||||
sliding_average<50> m_rtt;
|
||||
// the average time between incoming pieces. Or, if there is no
|
||||
// outstanding request, the time since the piece was requested. It
|
||||
// is essentially an estimate of the time it will take to completely
|
||||
// receive a payload message after it has been requested.
|
||||
sliding_average<20> m_request_time;
|
||||
|
||||
// keep the io_service running as long as we
|
||||
// have peer connections
|
||||
|
|
|
@ -71,6 +71,7 @@ struct sliding_average
|
|||
|
||||
int mean() const { return m_num_samples > 0 ? (m_mean + 32) / 64 : 0; }
|
||||
int avg_deviation() const { return m_num_samples > 1 ? (m_average_deviation + 32) / 64 : 0; }
|
||||
int num_samples() const { return m_num_samples; }
|
||||
|
||||
private:
|
||||
// both of these are fixed point values (* 64)
|
||||
|
|
|
@ -2445,21 +2445,6 @@ namespace libtorrent
|
|||
{
|
||||
if (i->block != b) continue;
|
||||
in_req_queue = true;
|
||||
if (i->receiving == false)
|
||||
{
|
||||
i->receiving = true;
|
||||
// if send_buffer_offset is greater then or equal to 0, it means
|
||||
// the callback of the send operation when we sent this
|
||||
// request hasn't come back yet, and we're already
|
||||
// receiving the response from it. Count the rtt as 0.
|
||||
int rtt = (i->send_buffer_offset >= 0) ? 0
|
||||
: int(total_milliseconds(time_now_hires() - i->request_time));
|
||||
m_rtt.add_sample(rtt);
|
||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
peer_log("*** RTT: %d ms [%d +/- %d ms]", rtt, m_rtt.mean()
|
||||
, m_rtt.avg_deviation());
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2653,7 +2638,7 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
ptime now = time_now();
|
||||
ptime now = time_now_hires();
|
||||
|
||||
t->need_picker();
|
||||
|
||||
|
@ -2717,6 +2702,14 @@ namespace libtorrent
|
|||
|
||||
if (m_disconnecting) return;
|
||||
|
||||
m_request_time.add_sample(total_milliseconds(now - m_requested));
|
||||
#if defined TORRENT_LOGGING \
|
||||
|| defined TORRENT_ERROR_LOGGING \
|
||||
|| defined TORRENT_VERBOSE_LOGGING
|
||||
peer_log("*** REQUEST-TIME (%d +- %d ms)"
|
||||
, m_request_time.mean(), m_request_time.avg_deviation());
|
||||
#endif
|
||||
|
||||
// we completed an incoming block, and there are still outstanding
|
||||
// requests. The next block we expect to receive now has another
|
||||
// timeout period until we time out. So, reset the timer.
|
||||
|
@ -2732,7 +2725,7 @@ namespace libtorrent
|
|||
// we received a request within the timeout, make sure this peer is
|
||||
// not snubbed anymore
|
||||
if (total_seconds(now - m_requested)
|
||||
< m_settings.get_int(settings_pack::request_timeout)
|
||||
< request_timeout()
|
||||
&& m_snubbed)
|
||||
{
|
||||
m_snubbed = false;
|
||||
|
@ -2783,6 +2776,14 @@ namespace libtorrent
|
|||
, performance_alert::too_high_disk_queue_limit));
|
||||
}
|
||||
|
||||
m_request_time.add_sample(total_milliseconds(now - m_requested));
|
||||
#if defined TORRENT_LOGGING \
|
||||
|| defined TORRENT_ERROR_LOGGING \
|
||||
|| defined TORRENT_VERBOSE_LOGGING
|
||||
peer_log("*** REQUEST-TIME (%d +- %d ms)"
|
||||
, m_request_time.mean(), m_request_time.avg_deviation());
|
||||
#endif
|
||||
|
||||
// we completed an incoming block, and there are still outstanding
|
||||
// requests. The next block we expect to receive now has another
|
||||
// timeout period until we time out. So, reset the timer.
|
||||
|
@ -4205,6 +4206,35 @@ namespace libtorrent
|
|||
return false;
|
||||
}
|
||||
|
||||
int peer_connection::request_timeout() const
|
||||
{
|
||||
const int deviation = m_request_time.avg_deviation();
|
||||
const int avg = m_request_time.mean();
|
||||
|
||||
int ret;
|
||||
if (m_request_time.num_samples() < 2)
|
||||
{
|
||||
if (m_request_time.num_samples() == 0)
|
||||
return m_settings.get_int(settings_pack::request_timeout);
|
||||
|
||||
ret = avg + avg / 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = avg + deviation * 3;
|
||||
}
|
||||
|
||||
// ret is milliseconds, the return value is seconds. Convert to
|
||||
// seconds and round up
|
||||
ret = (std::min)((ret + 999) / 1000
|
||||
, m_settings.get_int(settings_pack::request_timeout));
|
||||
|
||||
// timeouts should never be less than 2 seconds. The granularity is whole
|
||||
// seconds, and only checked once per second. 2 is the minimum to avoid
|
||||
// being considered timed out instantly
|
||||
return (std::max)(2, ret);
|
||||
}
|
||||
|
||||
void peer_connection::get_peer_info(peer_info& p) const
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
|
@ -4214,7 +4244,7 @@ namespace libtorrent
|
|||
|
||||
p.download_rate_peak = m_download_rate_peak;
|
||||
p.upload_rate_peak = m_upload_rate_peak;
|
||||
p.rtt = m_rtt.mean();
|
||||
p.rtt = m_request_time.mean();
|
||||
p.down_speed = statistics().download_rate();
|
||||
p.up_speed = statistics().upload_rate();
|
||||
p.payload_down_speed = statistics().download_payload_rate();
|
||||
|
@ -4228,7 +4258,7 @@ namespace libtorrent
|
|||
p.num_pieces = m_num_pieces;
|
||||
if (m_download_queue.empty()) p.request_timeout = -1;
|
||||
else p.request_timeout = int(total_seconds(m_requested - now)
|
||||
+ m_settings.get_int(settings_pack::request_timeout));
|
||||
+ request_timeout());
|
||||
|
||||
p.download_queue_time = download_queue_time();
|
||||
p.queue_bytes = m_outstanding_bytes;
|
||||
|
@ -4668,13 +4698,10 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: 3 instead of using settings_pack::request_timeout, use
|
||||
// m_rtt.mean() + m_rtt.avg_deviation() * 2 or something like that.
|
||||
// the configuration option could hopefully be removed
|
||||
if (may_timeout
|
||||
&& !m_download_queue.empty()
|
||||
&& m_quota[download_channel] > 0
|
||||
&& now > m_requested + seconds(m_settings.get_int(settings_pack::request_timeout)))
|
||||
&& now > m_requested + seconds(request_timeout()))
|
||||
{
|
||||
snub_peer();
|
||||
}
|
||||
|
@ -6020,12 +6047,10 @@ namespace libtorrent
|
|||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
m_rtt.add_sample(int(total_milliseconds(completed - m_connect)));
|
||||
|
||||
#if defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||
{
|
||||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
t->debug_log("END connect [%p] (RTT: %d ms)", this, m_rtt.mean());
|
||||
t->debug_log("END connect [%p]", this);
|
||||
m_connect_time = completed;
|
||||
}
|
||||
#endif
|
||||
|
@ -6102,8 +6127,7 @@ namespace libtorrent
|
|||
|
||||
TORRENT_ASSERT(m_socket);
|
||||
#if defined TORRENT_VERBOSE_LOGGING
|
||||
peer_log(">>> COMPLETED [ ep: %s rtt: %d ]"
|
||||
, print_endpoint(m_remote).c_str(), m_rtt.mean());
|
||||
peer_log(">>> COMPLETED [ ep: %s ]", print_endpoint(m_remote).c_str());
|
||||
#endif
|
||||
|
||||
// set the socket to non-blocking, so that we can
|
||||
|
@ -6202,7 +6226,6 @@ namespace libtorrent
|
|||
if (i->send_buffer_offset < 0) continue;
|
||||
i->send_buffer_offset -= bytes_transferred;
|
||||
if (i->send_buffer_offset >= 0) continue;
|
||||
i->request_time = now;
|
||||
i->send_buffer_offset = -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ namespace libtorrent
|
|||
SET(stop_tracker_timeout, 5, 0),
|
||||
SET(tracker_maximum_response_length, 1024*1024, 0),
|
||||
SET(piece_timeout, 20, 0),
|
||||
SET(request_timeout, 50, 0),
|
||||
SET(request_timeout, 60, 0),
|
||||
SET(request_queue_time, 3, 0),
|
||||
SET(max_allowed_in_request_queue, 500, 0),
|
||||
SET(max_out_request_queue, 500, 0),
|
||||
|
|
Loading…
Reference in New Issue