diff --git a/ChangeLog b/ChangeLog index b420fe395..cfbef7bd7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * introduced a mechanism to be lighter on the disk when checking torrents * applied temporary memory storage optimization to when checking a torrent as well * removed hash_for_slot() from storage_interface. It is now implemented diff --git a/docs/manual.rst b/docs/manual.rst index c13818982..7a57d6640 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -3441,6 +3441,8 @@ session_settings int send_socket_buffer_size; bool optimize_hashing_for_speed; + + int file_checks_delay_per_block; }; ``user_agent`` this is the client identification to the tracker. @@ -3817,6 +3819,12 @@ is false, a single block will be allocated (16 kB), and the unhashed parts of the piece are read, one at a time, and hashed in this single block. This is appropriate on systems that are memory constrained. +``file_checks_delay_per_block`` is the number of milliseconds to sleep +in between disk read operations when checking torrents. This defaults +to 0, but can be set to higher numbers to slow down the rate at which +data is read from the disk while checking. This may be useful for +background tasks that doesn't matter if they take a bit longer, as long +as they leave disk I/O time for other processes. pe_settings =========== diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index 210cbf93b..e893e3d0b 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -318,9 +318,12 @@ namespace libtorrent mutable mutex_t m_queue_mutex; boost::condition m_signal; bool m_abort; + bool m_waiting_to_shutdown; std::list m_jobs; size_type m_queue_buffer_size; + ptime m_last_file_check; + // this protects the piece cache and related members mutable mutex_t m_piece_mutex; // write cache diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index 3fd2365ac..58c3b09cd 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -166,6 +166,7 @@ namespace libtorrent , recv_socket_buffer_size(0) , send_socket_buffer_size(0) , optimize_hashing_for_speed(true) + , file_checks_delay_per_block(0) {} // this is the user agent that will be sent to the tracker @@ -559,6 +560,16 @@ namespace libtorrent // optimized for memory usage instead of the // number of read operations bool optimize_hashing_for_speed; + + // if > 0, file checks will have a short + // delay between disk operations, to make it + // less intrusive on the system as a whole + // blocking the disk. This delay is specified + // in milliseconds and the delay will be this + // long per 16kiB block + // the default of 10 ms/16kiB will limit + // the checking rate to 1.6 MiB per second + int file_checks_delay_per_block; }; #ifndef TORRENT_DISABLE_DHT diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 84561e4e2..0f0725574 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -253,6 +253,7 @@ namespace libtorrent disk_io_thread::disk_io_thread(asio::io_service& ios, int block_size) : disk_buffer_pool(block_size) , m_abort(false) + , m_waiting_to_shutdown(false) , m_queue_buffer_size(0) , m_ios(ios) , m_work(io_service::work(m_ios)) @@ -272,6 +273,7 @@ namespace libtorrent { mutex_t::scoped_lock l(m_queue_mutex); disk_io_job j; + m_waiting_to_shutdown = true; j.action = disk_io_job::abort_thread; m_jobs.insert(m_jobs.begin(), j); m_signal.notify_all(); @@ -1217,7 +1219,7 @@ namespace libtorrent mutex_t::scoped_lock jl(m_queue_mutex); for (std::list::iterator i = m_jobs.begin(); - i != m_jobs.end();) + i != m_jobs.end();) { if (i->action == disk_io_job::read) { @@ -1540,6 +1542,20 @@ namespace libtorrent int piece_size = j.storage->info()->piece_length(); for (int processed = 0; processed < 4 * 1024 * 1024; processed += piece_size) { + ptime now = time_now(); + if (now - m_last_file_check < milliseconds(m_settings.file_checks_delay_per_block)) + { + int sleep_time = m_settings.file_checks_delay_per_block + * (piece_size / (16 * 1024)) + - total_milliseconds(now - m_last_file_check); + + boost::thread::sleep(boost::get_system_time() + + boost::posix_time::milliseconds(sleep_time)); + } + m_last_file_check = time_now(); + + if (m_waiting_to_shutdown) break; + ret = j.storage->check_files(j.piece, j.offset, j.str); #ifndef BOOST_NO_EXCEPTIONS diff --git a/src/session.cpp b/src/session.cpp index e76abad6b..187399730 100644 --- a/src/session.cpp +++ b/src/session.cpp @@ -125,6 +125,11 @@ namespace libtorrent set.use_parole_mode = false; set.prioritize_partial_pieces = true; + // be extra nice on the hard drive when running + // on embedded devices. This might slow down + // torrent checking + set.file_checks_delay_per_block = 15; + // only have 4 files open at a time set.file_pool_size = 4; diff --git a/src/session_impl.cpp b/src/session_impl.cpp index eaa0c4bfb..b79b7537f 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -639,6 +639,7 @@ namespace aux { if (m_settings.cache_size != s.cache_size || m_settings.cache_expiry != s.cache_expiry || m_settings.optimize_hashing_for_speed != s.optimize_hashing_for_speed + || m_settings.file_checks_delay_per_block != s.file_checks_delay_per_block #ifndef TORRENT_DISABLE_MLOCK || m_settings.lock_disk_cache != s.lock_disk_cache #endif