prevent read jobs from starving in the disk I/O thread

This commit is contained in:
Arvid Norberg 2011-03-20 19:17:59 +00:00
parent 4a40a13a6c
commit 2dfd1a972b
4 changed files with 28 additions and 1 deletions

View File

@ -4381,6 +4381,7 @@ session_settings
bool smooth_connects;
bool always_send_user_agent;
bool apply_ip_filter_to_trackers;
int read_job_every;
};
``version`` is automatically set to the libtorrent version you're using
@ -5238,6 +5239,13 @@ IP filter applies to trackers as well as peers. If this is set to false,
trackers are exempt from the IP filter (if there is one). If no IP filter
is set, this setting is irrelevant.
``read_job_every`` is used to avoid starvation of read jobs in the disk I/O
thread. By default, read jobs are deferred, sorted by physical disk location
and serviced once all write jobs have been issued. In scenarios where the
download rate is enough to saturate the disk, there's a risk the read jobs will
never be serviced. With this setting, every *x* write job, issued in a row, will
instead pick one read job off of the sorted queue, where *x* is ``read_job_every``.
pe_settings
===========

View File

@ -267,6 +267,7 @@ namespace libtorrent
, smooth_connects(true)
, always_send_user_agent(false)
, apply_ip_filter_to_trackers(true)
, read_job_every(10)
{}
// libtorrent version. Used for forward binary compatibility
@ -1064,6 +1065,11 @@ namespace libtorrent
// if true, trackers will also be filtered by the IP
// filter, otherwise they are exempt
bool apply_ip_filter_to_trackers;
// to avoid write jobs starving read jobs, if this many
// write jobs have been taking priority in a row, service
// one read job
int read_job_every;
};
#ifndef TORRENT_DISABLE_DHT

View File

@ -1559,6 +1559,7 @@ namespace libtorrent
read_jobs_t::iterator elevator_job_pos = m_sorted_read_jobs.begin();
size_type last_elevator_pos = 0;
bool need_update_elevator_pos = false;
int immediate_jobs_in_row = 0;
for (;;)
{
@ -1618,7 +1619,14 @@ namespace libtorrent
m_queue_time.add_sample(total_microseconds(now - j.start_time));
ptime operation_start = now;
if (!m_jobs.empty())
// make sure we don't starve out the read queue by just issuing
// write jobs constantly, mix in a read job every now and then
// with a configurable ratio
bool pick_read_job = m_jobs.empty()
|| (immediate_jobs_in_row >= m_settings.read_job_every
&& !m_sorted_read_jobs.empty());
if (!pick_read_job)
{
// we have a job in the job queue. If it's
// a read operation and we are allowed to
@ -1702,6 +1710,8 @@ namespace libtorrent
m_cache_stats.cumulative_job_time += total_milliseconds(now - operation_start);
continue;
}
++immediate_jobs_in_row;
}
else
{
@ -1710,6 +1720,8 @@ namespace libtorrent
// job queue lock anymore
jl.unlock();
immediate_jobs_in_row = 0;
TORRENT_ASSERT(!m_sorted_read_jobs.empty());
// if m_sorted_read_jobs used to be empty,

View File

@ -363,6 +363,7 @@ namespace aux {
TORRENT_SETTING(integer, smooth_connects)
TORRENT_SETTING(boolean, always_send_user_agent)
TORRENT_SETTING(boolean, apply_ip_filter_to_trackers)
TORRENT_SETTING(integer, read_job_every)
};
#undef TORRENT_SETTING