diff --git a/include/libtorrent/platform_util.hpp b/include/libtorrent/platform_util.hpp index 443b9a681..3dcaaff6a 100644 --- a/include/libtorrent/platform_util.hpp +++ b/include/libtorrent/platform_util.hpp @@ -5,6 +5,8 @@ namespace libtorrent { + int max_open_files(); + boost::uint64_t total_physical_ram(); } diff --git a/src/disk_buffer_pool.cpp b/src/disk_buffer_pool.cpp index 725c0b4f9..25e927c8c 100644 --- a/src/disk_buffer_pool.cpp +++ b/src/disk_buffer_pool.cpp @@ -56,25 +56,6 @@ POSSIBILITY OF SUCH DAMAGE. #include #endif -#if TORRENT_USE_RLIMIT - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wlong-long" -#endif // __GNUC__ - -#include - -// capture this here where warnings are disabled (the macro generates warnings) -const rlim_t rlimit_as = RLIMIT_AS; -const rlim_t rlim_infinity = RLIM_INFINITY; - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif // __GNUC__ - -#endif // TORRENT_USE_RLIMIT - #ifdef TORRENT_LINUX #include #endif diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index f7fc8225e..efa3323b3 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/error.hpp" #include "libtorrent/file_pool.hpp" #include "libtorrent/torrent_info.hpp" +#include "libtorrent/platform_util.hpp" #include #include #include @@ -174,21 +175,14 @@ namespace libtorrent m_disk_cache.set_settings(m_settings, ec); TORRENT_ASSERT(!ec); -#if TORRENT_USE_RLIMIT - // ---- auto-cap open files ---- - - struct rlimit rl; - if (getrlimit(RLIMIT_NOFILE, &rl) == 0) - { - // deduct some margin for epoll/kqueue, log files, - // futexes, shared objects etc. - rl.rlim_cur -= 20; - - // 80% of the available file descriptors should go to connections - // 20% goes towards regular files - m_file_pool.resize((std::min)(m_file_pool.size_limit(), int(rl.rlim_cur * 2 / 10))); - } -#endif // TORRENT_USE_RLIMIT + // deduct some margin for epoll/kqueue, log files, + // futexes, shared objects etc. + // 80% of the available file descriptors should go to connections + // 20% goes towards regular files + const int max_files = (std::min)((std::max)(5 + , (max_open_files() - 20) * 2 / 10) + , m_file_pool.size_limit()); + m_file_pool.resize(max_files); } disk_io_thread::~disk_io_thread() @@ -387,7 +381,7 @@ namespace libtorrent // they are ready to be flushed. If so, flush them all, // otherwise, hold off bool range_full = true; - + cached_piece_entry* first_piece = NULL; DLOG("try_flush_hashed: multi-piece: "); for (int i = range_start; i < range_end; ++i) diff --git a/src/platform_util.cpp b/src/platform_util.cpp index cc4e02733..fd9e31a76 100644 --- a/src/platform_util.cpp +++ b/src/platform_util.cpp @@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/aux_/disable_warnings_push.hpp" #include +#include #if TORRENT_USE_RLIMIT @@ -48,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE. // capture this here where warnings are disabled (the macro generates warnings) const rlim_t rlimit_as = RLIMIT_AS; +const rlim_t rlimit_nofile = RLIMIT_NOFILE; const rlim_t rlim_infinity = RLIM_INFINITY; #ifdef __GNUC__ @@ -70,8 +72,33 @@ const rlim_t rlim_infinity = RLIM_INFINITY; namespace libtorrent { + int max_open_files() + { +#if defined TORRENT_BUILD_SIMULATOR + return 256; +#elif TORRENT_USE_RLIMIT + + struct rlimit rl; + if (getrlimit(RLIMIT_NOFILE, &rl) == 0) + { + if (rl.rlim_cur == rlim_infinity) + return (std::numeric_limits::max)(); + + return rl.rlim_cur; + } + return 1024; +#else + // this seems like a reasonable limit for windows. + // http://blogs.msdn.com/b/oldnewthing/archive/2007/07/18/3926581.aspx + return 10000; +#endif + } + boost::uint64_t total_physical_ram() { +#if defined TORRENT_BUILD_SIMULATOR + return boost::uint64_t(4) * 1024 * 1024 * 1024; +#else // 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 @@ -116,6 +143,7 @@ namespace libtorrent } #endif return ret; +#endif // TORRENT_BUILD_SIMULATOR } } diff --git a/src/session_impl.cpp b/src/session_impl.cpp index ef260ff27..d9d231b22 100644 --- a/src/session_impl.cpp +++ b/src/session_impl.cpp @@ -114,6 +114,7 @@ const rlim_t rlim_infinity = RLIM_INFINITY; #include "libtorrent/torrent_handle.hpp" #include "libtorrent/choker.hpp" #include "libtorrent/error.hpp" +#include "libtorrent/platform_util.hpp" #ifndef TORRENT_DISABLE_LOGGING @@ -523,33 +524,19 @@ namespace aux { #endif // TORRENT_DISABLE_LOGGING -#if TORRENT_USE_RLIMIT // ---- auto-cap max connections ---- - - struct rlimit rl; - if (getrlimit(RLIMIT_NOFILE, &rl) == 0) - { + int max_files = max_open_files(); + // deduct some margin for epoll/kqueue, log files, + // futexes, shared objects etc. + // 80% of the available file descriptors should go to connections + m_settings.set_int(settings_pack::connections_limit, (std::min)( + m_settings.get_int(settings_pack::connections_limit) + , (std::max)(5, (max_files - 20) * 8 / 10))); + // 20% goes towards regular files (see disk_io_thread) #ifndef TORRENT_DISABLE_LOGGING - session_log(" max number of open files: %d", int(rl.rlim_cur)); -#endif - // deduct some margin for epoll/kqueue, log files, - // futexes, shared objects etc. - rl.rlim_cur -= 20; + session_log(" max connections: %d", m_settings.get_int(settings_pack::connections_limit)); + session_log(" max files: %d", max_files); - // 80% of the available file descriptors should go to connections - m_settings.set_int(settings_pack::connections_limit, (std::min)( - m_settings.get_int(settings_pack::connections_limit) - , int(rl.rlim_cur * 8 / 10))); - // 20% goes towards regular files (see disk_io_thread) -#ifndef TORRENT_DISABLE_LOGGING - session_log(" max connections: %d", m_settings.get_int(settings_pack::connections_limit)); - session_log(" max files: %d", int(rl.rlim_cur * 2 / 10)); -#endif - } -#endif // TORRENT_USE_RLIMIT - - -#ifndef TORRENT_DISABLE_LOGGING session_log(" generated peer ID: %s", m_peer_id.to_string().c_str()); #endif @@ -6292,21 +6279,15 @@ retry: void session_impl::update_connections_limit() { - if (m_settings.get_int(settings_pack::connections_limit) <= 0) - { - m_settings.set_int(settings_pack::connections_limit, (std::numeric_limits::max)()); -#if TORRENT_USE_RLIMIT - rlimit l; - if (getrlimit(RLIMIT_NOFILE, &l) == 0 - && l.rlim_cur != rlim_infinity) - { - m_settings.set_int(settings_pack::connections_limit - , l.rlim_cur - m_settings.get_int(settings_pack::file_pool_size)); - if (m_settings.get_int(settings_pack::connections_limit) < 5) - m_settings.set_int(settings_pack::connections_limit, 5); - } -#endif - } + int limit = m_settings.get_int(settings_pack::connections_limit); + + if (limit <= 0) + limit = (std::numeric_limits::max)(); + + limit = (std::max)(5, (std::min)(limit + , max_open_files() - 20 - m_settings.get_int(settings_pack::file_pool_size))); + + m_settings.set_int(settings_pack::connections_limit, limit); if (num_connections() > m_settings.get_int(settings_pack::connections_limit) && !m_torrents.empty())