diff --git a/ChangeLog b/ChangeLog index 2c05ab326..62829125e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * made the default cache size depend on available physical RAM * added flags to torrent::status() that can filter which values are calculated * support 'explicit read cache' which keeps a specific set of pieces in the read cache, without implicitly caching other pieces diff --git a/docs/manual.rst b/docs/manual.rst index bfa7a16b5..802c30e2a 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -4060,10 +4060,12 @@ in parole mode fails the hash check, it is banned. If a peer participates in a piece that passes the hash check, it is taken out of parole mode. ``cache_size`` is the disk write and read cache. It is specified in units of -16 KiB blocks. It defaults to 1024 (= 16 MB). Buffers that are part of a peer's -send or receive buffer also count against this limit. Send and receive buffers -will never be denied to be allocated, but they will cause the actual cached blocks -to be flushed or evicted. +16 KiB blocks. Buffers that are part of a peer's send or receive buffer also +count against this limit. Send and receive buffers will never be denied to be +allocated, but they will cause the actual cached blocks to be flushed or evicted. +If this is set to -1, the cache size is automatically set to the amount +of physical RAM available in the machine divided by 8. If the amount of physical +RAM cannot be determined, it's set to 1024 (= 16 MiB). Disk buffers are allocated using a pool allocator, the number of blocks that are allocated at a time when the pool needs to grow can be specified in diff --git a/include/libtorrent/aux_/session_impl.hpp b/include/libtorrent/aux_/session_impl.hpp index 8e6d74fd5..6a2b3ffee 100644 --- a/include/libtorrent/aux_/session_impl.hpp +++ b/include/libtorrent/aux_/session_impl.hpp @@ -390,6 +390,7 @@ namespace libtorrent // private: + void update_disk_thread_settings(); void on_dht_state_callback(condition& c , entry& e, bool& done) const; void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih); diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index 1d7bff10a..d65e59f4a 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -431,6 +431,9 @@ namespace libtorrent std::ofstream m_log; #endif + // the amount of physical ram in the machine + boost::uint64_t m_physical_ram; + io_service& m_ios; boost::function m_queue_callback; diff --git a/include/libtorrent/session_settings.hpp b/include/libtorrent/session_settings.hpp index b57b43cc0..25938fc5c 100644 --- a/include/libtorrent/session_settings.hpp +++ b/include/libtorrent/session_settings.hpp @@ -434,7 +434,9 @@ namespace libtorrent bool use_parole_mode; // the disk write cache, specified in 16 KiB blocks. - // default is 512 (= 8 MB) + // default is 1024 (= 16 MiB). -1 means automatic, which + // adjusts the cache size depending on the amount + // of physical RAM in the machine. int cache_size; // this is the number of disk buffer blocks (16 kiB) diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 80a37b3cf..ef0c87e5f 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -51,6 +51,10 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif +#ifdef TORRENT_BSD +#include +#endif + namespace libtorrent { bool should_cancel_on_abort(disk_io_job const& j); @@ -288,6 +292,7 @@ namespace libtorrent , m_waiting_to_shutdown(false) , m_queue_buffer_size(0) , m_last_file_check(time_now_hires()) + , m_physical_ram(0) , m_ios(ios) , m_queue_callback(queue_callback) , m_work(io_service::work(m_ios)) @@ -297,6 +302,40 @@ namespace libtorrent #ifdef TORRENT_DISK_STATS m_log.open("disk_io_thread.log", std::ios::trunc); #endif + + // figure out how much physical RAM there is in + // this machine. This is used for automatically + // sizing the disk cache size when it's set to + // automatic. +#ifdef TORRENT_BSD + int mib[2] = { CTL_HW, HW_MEMSIZE }; + size_t len = sizeof(m_physical_ram); + if (sysctl(mib, 2, &m_physical_ram, &len, NULL, 0) != 0) + m_physical_ram = 0; +#elif defined TORRENT_WINDOWS + MEMORYSTATUSEX ms; + if (GlobalMemoryStatusEx(&ms)) + m_physical_ram = ms.ullTotalPhys; + else + m_physical_ram = 0; +#elif defined TORRENT_LINUX + m_physical_ram = sysconf(_SC_PHYS_PAGES); + m_physical_ram *= sysconf(_SC_PAGESIZE); +#elif defined TORRENT_AMIGA + m_physical_ram = AvailMem(MEMF_PUBLIC); +#endif + +#if TORRENT_USE_RLIMIT + if (m_physical_ram > 0) + { + struct rlimit r; + if (getrlimit(RLIMIT_AS, &r) == 0 && r.rlim_cur != RLIM_INFINITY) + { + if (m_physical_ram > r.rlim_cur) + m_physical_ram = r.rlim_cur; + } + } +#endif } disk_io_thread::~disk_io_thread() @@ -1629,6 +1668,17 @@ namespace libtorrent setiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD , m_settings.low_prio_disk ? IOPOL_THROTTLE : IOPOL_DEFAULT); #endif + if (m_settings.cache_size == -1) + { + // the cache size is set to automatic. Make it + // depend on the amount of physical RAM + // if we don't know how much RAM we have, just set the + // cache size to 16 MiB (1024 blocks) + if (m_physical_ram == 0) + m_settings.cache_size = 1024; + else + m_settings.cache_size = m_physical_ram / 8 / m_block_size; + } break; } case disk_io_job::abort_torrent: diff --git a/src/session_impl.cpp b/src/session_impl.cpp index 869b6b09d..86926a23f 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -762,10 +762,8 @@ namespace aux { { session_category const& c = all_settings[i]; settings = e.dict_find_dict(c.name); - if (settings) - { - load_struct(*settings, reinterpret_cast(this) + c.offset, c.map, c.num_entries); - } + if (!settings) continue; + load_struct(*settings, reinterpret_cast(this) + c.offset, c.map, c.num_entries); } #ifndef TORRENT_DISABLE_DHT settings = e.dict_find_dict("dht"); @@ -808,6 +806,7 @@ namespace aux { } } #endif + update_disk_thread_settings(); } #ifndef TORRENT_DISABLE_GEO_IP @@ -1062,6 +1061,14 @@ namespace aux { return m_ip_filter; } + void session_impl::update_disk_thread_settings() + { + disk_io_job j; + j.buffer = (char*)&m_settings; + j.action = disk_io_job::update_settings; + m_disk_thread.add_job(j); + } + void session_impl::set_settings(session_settings const& s) { INVARIANT_CHECK; @@ -1159,12 +1166,7 @@ namespace aux { if (m_settings.connection_speed < 0) m_settings.connection_speed = 200; if (update_disk_io_thread) - { - disk_io_job j; - j.buffer = (char*)&m_settings; - j.action = disk_io_job::update_settings; - m_disk_thread.add_job(j); - } + update_disk_thread_settings(); if (m_allowed_upload_slots <= m_settings.num_optimistic_unchoke_slots / 2) {