support disk I/O priority setting

This commit is contained in:
Arvid Norberg 2010-01-23 03:02:32 +00:00
parent 9e98bfd204
commit a046850130
12 changed files with 82 additions and 8 deletions

View File

@ -95,6 +95,7 @@
* added support for storing per-peer rate limits across reconnects * added support for storing per-peer rate limits across reconnects
* improved fallocate support * improved fallocate support
* fixed magnet link issue when using resume data * fixed magnet link issue when using resume data
* support disk I/O priority settings
release 0.14.9 release 0.14.9

View File

@ -99,6 +99,13 @@ void bind_session_settings()
.def_readwrite("disk_cache_algorithm", &session_settings::disk_cache_algorithm) .def_readwrite("disk_cache_algorithm", &session_settings::disk_cache_algorithm)
.def_readwrite("read_cache_line_size", &session_settings::read_cache_line_size) .def_readwrite("read_cache_line_size", &session_settings::read_cache_line_size)
.def_readwrite("write_cache_line_size", &session_settings::write_cache_line_size) .def_readwrite("write_cache_line_size", &session_settings::write_cache_line_size)
.def_readwrite("optimistic_disk_retry", &session_settings::optimistic_disk_retry)
.def_readwrite("disable_hash_checks", &session_settings::disable_hash_checks)
.def_readwrite("allow_reordered_disk_operations", &session_settings::allow_reordered_disk_operations)
.def_readwrite("allow_i2p_mixed", &session_settings::allow_i2p_mixed)
.def_readwrite("max_suggest_pieces", &session_settings::max_suggest_pieces)
.def_readwrite("drop_skipped_requests", &session_settings::drop_skipped_requests)
.def_readwrite("low_prio_disk", &session_settings::low_prio_disk)
; ;
enum_<proxy_settings::proxy_type>("proxy_type") enum_<proxy_settings::proxy_type>("proxy_type")

View File

@ -3718,6 +3718,8 @@ session_settings
int max_suggest_pieces; int max_suggest_pieces;
bool drop_skipped_requests; bool drop_skipped_requests;
bool low_prio_disk;
}; };
``user_agent`` this is the client identification to the tracker. ``user_agent`` this is the client identification to the tracker.
@ -4180,6 +4182,13 @@ BitComet peers silently ignoring some requests. It may cause problems
at high rates, and high level of reordering in the uploading peer, that's at high rates, and high level of reordering in the uploading peer, that's
why it's disabled by default. why it's disabled by default.
``low_prio_disk`` determines if the disk I/O should use a normal
or low priority policy. This defaults to true, which means that
it's low priority by default. Other processes doing disk I/O will
normally take priority in this mode. This is meant to improve the
overall responsiveness of the system while downloading in the
background. For high-performance server setups, this might not
be desirable.
pe_settings pe_settings
=========== ===========

View File

@ -253,6 +253,7 @@ namespace libtorrent
{ {
disk_io_thread(io_service& ios disk_io_thread(io_service& ios
, boost::function<void()> const& queue_callback , boost::function<void()> const& queue_callback
, file_pool& fp
, int block_size = 16 * 1024); , int block_size = 16 * 1024);
~disk_io_thread(); ~disk_io_thread();
@ -399,6 +400,10 @@ namespace libtorrent
// exist anymore, and crash. This prevents that. // exist anymore, and crash. This prevents that.
boost::optional<io_service::work> m_work; boost::optional<io_service::work> m_work;
// reference to the file_pool which is a member of
// the session_impl object
file_pool& m_file_pool;
// thread for performing blocking disk io operations // thread for performing blocking disk io operations
thread m_disk_io_thread; thread m_disk_io_thread;
}; };

View File

@ -241,6 +241,12 @@ namespace libtorrent
size_type phys_offset(size_type offset); size_type phys_offset(size_type offset);
#ifdef TORRENT_WINDOWS
HANDLE native_handle() const { return m_file_handle; }
#else
int native_handle() const { return m_fd; }
#endif
private: private:
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS

View File

@ -52,7 +52,7 @@ namespace libtorrent
{ {
struct TORRENT_EXPORT file_pool : boost::noncopyable struct TORRENT_EXPORT file_pool : boost::noncopyable
{ {
file_pool(int size = 40): m_size(size) {} file_pool(int size = 40): m_size(size), m_low_prio_io(true) {}
boost::shared_ptr<file> open_file(void* st, std::string const& p boost::shared_ptr<file> open_file(void* st, std::string const& p
, int m, error_code& ec); , int m, error_code& ec);
@ -60,12 +60,15 @@ namespace libtorrent
void release(std::string const& p); void release(std::string const& p);
void resize(int size); void resize(int size);
int size_limit() const { return m_size; } int size_limit() const { return m_size; }
void set_low_prio_io(bool b) { m_low_prio_io = b; }
private: private:
file_pool(file_pool const&);
void remove_oldest(); void remove_oldest();
int m_size; int m_size;
bool m_low_prio_io;
struct lru_file_entry struct lru_file_entry
{ {

View File

@ -185,6 +185,7 @@ namespace libtorrent
, allow_i2p_mixed(false) , allow_i2p_mixed(false)
, max_suggest_pieces(10) , max_suggest_pieces(10)
, drop_skipped_requests(false) , drop_skipped_requests(false)
, low_prio_disk(true)
{} {}
// this is the user agent that will be sent to the tracker // this is the user agent that will be sent to the tracker
@ -675,6 +676,13 @@ namespace libtorrent
// satisfied after the equivalence of the entire // satisfied after the equivalence of the entire
// request queue has been received, will be considered lost // request queue has been received, will be considered lost
bool drop_skipped_requests; bool drop_skipped_requests;
// if this is set to true, the disk I/O will be
// run at lower-than-normal priority. This is
// intended to make the machine more responsive
// to foreground tasks, while bittorrent runs
// in the background
bool low_prio_disk;
}; };
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT

View File

@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/invariant_check.hpp" #include "libtorrent/invariant_check.hpp"
#include "libtorrent/error_code.hpp" #include "libtorrent/error_code.hpp"
#include "libtorrent/error.hpp" #include "libtorrent/error.hpp"
#include "libtorrent/file_pool.hpp"
#include <boost/scoped_array.hpp> #include <boost/scoped_array.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
@ -280,6 +281,7 @@ namespace libtorrent
disk_io_thread::disk_io_thread(io_service& ios disk_io_thread::disk_io_thread(io_service& ios
, boost::function<void()> const& queue_callback , boost::function<void()> const& queue_callback
, file_pool& fp
, int block_size) , int block_size)
: disk_buffer_pool(block_size) : disk_buffer_pool(block_size)
, m_abort(false) , m_abort(false)
@ -289,6 +291,7 @@ namespace libtorrent
, m_ios(ios) , m_ios(ios)
, m_queue_callback(queue_callback) , m_queue_callback(queue_callback)
, m_work(io_service::work(m_ios)) , m_work(io_service::work(m_ios))
, m_file_pool(fp)
, m_disk_io_thread(boost::bind(&disk_io_thread::thread_fun, this)) , m_disk_io_thread(boost::bind(&disk_io_thread::thread_fun, this))
{ {
#ifdef TORRENT_DISK_STATS #ifdef TORRENT_DISK_STATS
@ -1570,7 +1573,21 @@ namespace libtorrent
TORRENT_ASSERT(s.cache_size >= 0); TORRENT_ASSERT(s.cache_size >= 0);
TORRENT_ASSERT(s.cache_expiry > 0); TORRENT_ASSERT(s.cache_expiry > 0);
#if defined TORRENT_WINDOWS
if (m_settings.low_prio_disk != s.low_prio_disk)
{
m_file_pool.set_low_prio_io(s.low_prio_disk);
// we need to close all files, since the prio
// only takes affect when files are opened
m_file_pool.release(0);
}
#endif
m_settings = s; m_settings = s;
m_file_pool.resize(m_settings.file_pool_size);
#if defined __APPLE__ && defined __MACH__ && MAC_OS_X_VERSION_MIN_REQUIRED >= 1050
setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD
, m_settings.low_prio_disk ? IOPOL_THROTTLE : IOPOL_DEFAULT);
#endif
break; break;
} }
case disk_io_job::abort_torrent: case disk_io_job::abort_torrent:

View File

@ -80,6 +80,15 @@ namespace libtorrent
m_files.erase(i); m_files.erase(i);
return boost::shared_ptr<file>(); return boost::shared_ptr<file>();
} }
#ifdef TORRENT_WINDOWS
if (m_low_prio_io)
{
FILE_IO_PRIORITY_HINT_INFO priorityHint;
priorityHint.PriorityHint = IoPriorityHintLow;
result = SetFileInformationByHandle(e.file_ptr->native_handle(),
FileIoPriorityHintInfo, &priorityHint, sizeof(PriorityHint));
}
#endif
TORRENT_ASSERT(e.file_ptr->is_open()); TORRENT_ASSERT(e.file_ptr->is_open());
e.mode = m; e.mode = m;
} }
@ -126,10 +135,16 @@ namespace libtorrent
if (i != m_files.end()) m_files.erase(i); if (i != m_files.end()) m_files.erase(i);
} }
// closes files belonging to the specified
// storage. If 0 is passed, all files are closed
void file_pool::release(void* st) void file_pool::release(void* st)
{ {
mutex::scoped_lock l(m_mutex); mutex::scoped_lock l(m_mutex);
TORRENT_ASSERT(st != 0); if (st == 0)
{
m_files.clear();
return;
}
for (file_set::iterator i = m_files.begin(); for (file_set::iterator i = m_files.begin();
i != m_files.end();) i != m_files.end();)

View File

@ -175,6 +175,7 @@ namespace libtorrent
set.cache_buffer_chunk_size = 128; set.cache_buffer_chunk_size = 128;
set.read_cache_line_size = 512; set.read_cache_line_size = 512;
set.write_cache_line_size = 512; set.write_cache_line_size = 512;
set.low_prio_disk = false;
// one hour expiration // one hour expiration
set.cache_expiry = 60 * 60; set.cache_expiry = 60 * 60;

View File

@ -403,7 +403,7 @@ namespace aux {
, m_files(40) , m_files(40)
, m_io_service() , m_io_service()
, m_alerts(m_io_service) , m_alerts(m_io_service)
, m_disk_thread(m_io_service, boost::bind(&session_impl::on_disk_queue, this)) , m_disk_thread(m_io_service, boost::bind(&session_impl::on_disk_queue, this), m_files)
, m_half_open(m_io_service) , m_half_open(m_io_service)
, m_download_rate(peer_connection::download_channel) , m_download_rate(peer_connection::download_channel)
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT #ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
@ -1016,7 +1016,10 @@ namespace aux {
#ifndef TORRENT_DISABLE_MLOCK #ifndef TORRENT_DISABLE_MLOCK
|| m_settings.lock_disk_cache != s.lock_disk_cache || m_settings.lock_disk_cache != s.lock_disk_cache
#endif #endif
|| m_settings.use_read_cache != s.use_read_cache) || m_settings.use_read_cache != s.use_read_cache
|| m_settings.allow_reordered_disk_operations != s.allow_reordered_disk_operations
|| m_settings.file_pool_size != s.file_pool_size
|| m_settings.low_prio_disk != s.low_prio_disk)
update_disk_io_thread = true; update_disk_io_thread = true;
// if queuing settings were changed, recalculate // if queuing settings were changed, recalculate
@ -1037,7 +1040,6 @@ namespace aux {
m_disk_thread.add_job(j); m_disk_thread.add_job(j);
} }
m_files.resize(m_settings.file_pool_size);
if (!s.auto_upload_slots) m_allowed_upload_slots = m_max_uploads; if (!s.auto_upload_slots) m_allowed_upload_slots = m_max_uploads;
// replace all occurances of '\n' with ' '. // replace all occurances of '\n' with ' '.
std::string::iterator i = m_settings.user_agent.begin(); std::string::iterator i = m_settings.user_agent.begin();

View File

@ -243,7 +243,7 @@ void run_elevator_test()
{ {
error_code ec; error_code ec;
disk_io_thread dio(ios, &nop); disk_io_thread dio(ios, &nop, fp);
boost::intrusive_ptr<piece_manager> pm(new piece_manager(boost::shared_ptr<void>(), ti, "" boost::intrusive_ptr<piece_manager> pm(new piece_manager(boost::shared_ptr<void>(), ti, ""
, fp, dio, &create_test_storage, storage_mode_sparse)); , fp, dio, &create_test_storage, storage_mode_sparse));
@ -379,7 +379,7 @@ void run_storage_tests(boost::intrusive_ptr<torrent_info> info
{ {
file_pool fp; file_pool fp;
libtorrent::asio::io_service ios; libtorrent::asio::io_service ios;
disk_io_thread io(ios, boost::function<void()>()); disk_io_thread io(ios, boost::function<void()>(), fp);
boost::shared_ptr<int> dummy(new int); boost::shared_ptr<int> dummy(new int);
boost::intrusive_ptr<piece_manager> pm = new piece_manager(dummy, info boost::intrusive_ptr<piece_manager> pm = new piece_manager(dummy, info
, test_path, fp, io, default_storage_constructor, storage_mode); , test_path, fp, io, default_storage_constructor, storage_mode);
@ -601,7 +601,7 @@ void test_check_files(std::string const& test_path
file_pool fp; file_pool fp;
libtorrent::asio::io_service ios; libtorrent::asio::io_service ios;
disk_io_thread io(ios, boost::function<void()>()); disk_io_thread io(ios, boost::function<void()>(), fp);
boost::shared_ptr<int> dummy(new int); boost::shared_ptr<int> dummy(new int);
boost::intrusive_ptr<piece_manager> pm = new piece_manager(dummy, info boost::intrusive_ptr<piece_manager> pm = new piece_manager(dummy, info
, test_path, fp, io, default_storage_constructor, storage_mode); , test_path, fp, io, default_storage_constructor, storage_mode);