fix support for auto disk cache size and disk buffer pool allocator behavior

This commit is contained in:
arvidn 2016-03-05 11:02:41 -05:00 committed by arvidn
parent 5febe36106
commit 8ca76f9d59
6 changed files with 73 additions and 16 deletions

View File

@ -1451,8 +1451,8 @@ int main(int argc, char* argv[])
#endif // TORRENT_USE_I2P #endif // TORRENT_USE_I2P
case 'C': case 'C':
settings.set_int(settings_pack::cache_size, atoi(arg)); settings.set_int(settings_pack::cache_size, atoi(arg));
settings.set_bool(settings_pack::use_read_cache, atoi(arg) > 0); settings.set_bool(settings_pack::use_read_cache, atoi(arg) != 0);
settings.set_int(settings_pack::cache_buffer_chunk_size, atoi(arg) / 100); settings.set_int(settings_pack::cache_buffer_chunk_size, 0);
break; break;
case 'A': settings.set_int(settings_pack::allowed_fast_set_size, atoi(arg)); break; case 'A': settings.set_int(settings_pack::allowed_fast_set_size, atoi(arg)); break;
case 'R': settings.set_int(settings_pack::read_cache_line_size, atoi(arg)); break; case 'R': settings.set_int(settings_pack::read_cache_line_size, atoi(arg)); break;

View File

@ -97,7 +97,7 @@ TORRENT_TEST(session_stats)
// on alert // on alert
, [=](lt::alert const* a, lt::session& ses) , [=](lt::alert const* a, lt::session& ses)
{ {
lt::session_stats_alert const* ss = lt::alert_cast<session_stats_alert>(a); auto const* ss = lt::alert_cast<session_stats_alert>(a);
if (!ss) return; if (!ss) return;
// there's one downloading torrent // there's one downloading torrent

View File

@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "create_torrent.hpp" #include "create_torrent.hpp"
#include "settings.hpp" #include "settings.hpp"
#include "libtorrent/session.hpp" #include "libtorrent/session.hpp"
#include "libtorrent/session_stats.hpp"
#include "libtorrent/deadline_timer.hpp" #include "libtorrent/deadline_timer.hpp"
#include "libtorrent/settings_pack.hpp" #include "libtorrent/settings_pack.hpp"
#include "libtorrent/ip_filter.hpp" #include "libtorrent/ip_filter.hpp"
@ -194,6 +195,39 @@ void filter_ips(lt::session& ses)
ses.set_ip_filter(filter); ses.set_ip_filter(filter);
} }
void set_cache_size(lt::session& ses, int val)
{
using namespace libtorrent;
settings_pack pack;
pack.set_int(settings_pack::cache_size, val);
ses.apply_settings(pack);
}
int get_cache_size(lt::session& ses)
{
using namespace libtorrent;
std::vector<stats_metric> stats = session_stats_metrics();
int const read_cache_idx = find_metric_idx("disk.read_cache_blocks");
int const write_cache_idx = find_metric_idx("disk.write_cache_blocks");
TEST_CHECK(read_cache_idx >= 0);
TEST_CHECK(write_cache_idx >= 0);
ses.set_alert_notify([](){});
ses.post_session_stats();
std::vector<alert*> alerts;
ses.pop_alerts(&alerts);
int cache_size = -1;
for (auto const a : alerts)
{
if (auto const* st = alert_cast<session_stats_alert>(a))
{
cache_size = st->values[read_cache_idx];
cache_size += st->values[write_cache_idx];
break;
}
}
return cache_size;
}
void set_proxy(lt::session& ses, int proxy_type, int flags = 0, bool proxy_peer_connections = true) void set_proxy(lt::session& ses, int proxy_type, int flags = 0, bool proxy_peer_connections = true)
{ {
// apply the proxy settings to session 0 // apply the proxy settings to session 0
@ -391,3 +425,19 @@ TORRENT_TEST(no_proxy_utp_banned)
); );
} }
TORRENT_TEST(auto_disk_cache_size)
{
using namespace libtorrent;
run_test(
[](lt::session& ses0, lt::session& ses1) { set_cache_size(ses0, -1); },
[](lt::session& ses, lt::alert const* alert) {},
[](std::shared_ptr<lt::session> ses[2]) {
TEST_EQUAL(is_seed(*ses[0]), true);
int const cache_size = get_cache_size(*ses[0]);
printf("cache size: %d\n", cache_size);
// this assumes the test torrent is at least 4 blocks
TEST_CHECK(cache_size > 4);
}
);
}

View File

@ -371,11 +371,14 @@ namespace libtorrent
#else #else
if (m_using_pool_allocator) if (m_using_pool_allocator)
{ {
ret = static_cast<char*>(m_pool.malloc()); int const effective_block_size
int effective_block_size = m_cache_buffer_chunk_size = m_in_use >= m_max_use
? 20 // use small increments once we've exceeded the cache size
: m_cache_buffer_chunk_size
? m_cache_buffer_chunk_size ? m_cache_buffer_chunk_size
: (std::max)(m_max_use / 10, 1); : (std::max)(m_max_use / 10, 1);
m_pool.set_next_size(effective_block_size); m_pool.set_next_size(effective_block_size);
ret = static_cast<char*>(m_pool.malloc());
} }
else else
{ {
@ -453,7 +456,9 @@ namespace libtorrent
m_cache_buffer_chunk_size = sett.get_int(settings_pack::cache_buffer_chunk_size); m_cache_buffer_chunk_size = sett.get_int(settings_pack::cache_buffer_chunk_size);
m_lock_disk_cache = sett.get_bool(settings_pack::lock_disk_cache); m_lock_disk_cache = sett.get_bool(settings_pack::lock_disk_cache);
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR #ifndef TORRENT_DISABLE_POOL_ALLOCATOR
m_want_pool_allocator = sett.get_bool(settings_pack::use_disk_cache_pool); // if the chunk size is set to 1, there's no point in creating a pool
m_want_pool_allocator = sett.get_bool(settings_pack::use_disk_cache_pool)
&& (m_cache_buffer_chunk_size != 1);
// if there are no allocated blocks, it's OK to switch allocator // if there are no allocated blocks, it's OK to switch allocator
if (m_in_use == 0) if (m_in_use == 0)
m_using_pool_allocator = m_want_pool_allocator; m_using_pool_allocator = m_want_pool_allocator;
@ -476,7 +481,7 @@ namespace libtorrent
int const cache_size = sett.get_int(settings_pack::cache_size); int const cache_size = sett.get_int(settings_pack::cache_size);
if (cache_size < 0) if (cache_size < 0)
{ {
boost::uint64_t phys_ram = total_physical_ram(); boost::uint64_t const phys_ram = total_physical_ram();
if (phys_ram == 0) m_max_use = 1024; if (phys_ram == 0) m_max_use = 1024;
else m_max_use = phys_ram / 8 / m_block_size; else m_max_use = phys_ram / 8 / m_block_size;
@ -500,6 +505,8 @@ namespace libtorrent
m_exceeded_max_size = true; m_exceeded_max_size = true;
m_trigger_cache_trim(); m_trigger_cache_trim();
} }
if (m_cache_buffer_chunk_size > m_max_use)
m_cache_buffer_chunk_size = m_max_use;
} }
#if TORRENT_USE_ASSERTS #if TORRENT_USE_ASSERTS

View File

@ -1188,7 +1188,7 @@ namespace libtorrent
int disk_io_thread::do_read(disk_io_job* j, jobqueue_t& completed_jobs) int disk_io_thread::do_read(disk_io_job* j, jobqueue_t& completed_jobs)
{ {
if (!m_settings.get_bool(settings_pack::use_read_cache) if (m_settings.get_bool(settings_pack::use_read_cache) == false
|| m_settings.get_int(settings_pack::cache_size) == 0) || m_settings.get_int(settings_pack::cache_size) == 0)
{ {
// we're not using a cache. This is the simple path // we're not using a cache. This is the simple path
@ -1462,7 +1462,7 @@ namespace libtorrent
// should we put this write job in the cache? // should we put this write job in the cache?
// if we don't use the cache we shouldn't. // if we don't use the cache we shouldn't.
if (m_settings.get_bool(settings_pack::use_write_cache) if (m_settings.get_bool(settings_pack::use_write_cache)
&& m_settings.get_int(settings_pack::cache_size) > 0) && m_settings.get_int(settings_pack::cache_size) != 0)
{ {
mutex::scoped_lock l(m_cache_mutex); mutex::scoped_lock l(m_cache_mutex);
@ -1578,7 +1578,7 @@ namespace libtorrent
TORRENT_ASSERT(j->action == disk_io_job::read); TORRENT_ASSERT(j->action == disk_io_job::read);
if (m_settings.get_bool(settings_pack::use_read_cache) if (m_settings.get_bool(settings_pack::use_read_cache)
&& m_settings.get_int(settings_pack::cache_size) > 0) && m_settings.get_int(settings_pack::cache_size) != 0)
{ {
int ret = m_disk_cache.try_read(j); int ret = m_disk_cache.try_read(j);
if (ret >= 0) if (ret >= 0)
@ -1691,7 +1691,7 @@ namespace libtorrent
TORRENT_ASSERT(m_disk_cache.is_disk_buffer(j->buffer.disk_block)); TORRENT_ASSERT(m_disk_cache.is_disk_buffer(j->buffer.disk_block));
l_.unlock(); l_.unlock();
#endif #endif
if (m_settings.get_int(settings_pack::cache_size) > 0 if (m_settings.get_int(settings_pack::cache_size) != 0
&& m_settings.get_bool(settings_pack::use_write_cache)) && m_settings.get_bool(settings_pack::use_write_cache))
{ {
TORRENT_ASSERT((r.start % m_disk_cache.block_size()) == 0); TORRENT_ASSERT((r.start % m_disk_cache.block_size()) == 0);
@ -2327,7 +2327,7 @@ namespace libtorrent
} }
} }
if (pe == NULL && !m_settings.get_bool(settings_pack::use_read_cache)) if (pe == NULL && m_settings.get_bool(settings_pack::use_read_cache) == false)
{ {
l.unlock(); l.unlock();
// if there's no piece in the cache, and the read cache is disabled // if there's no piece in the cache, and the read cache is disabled
@ -2635,7 +2635,7 @@ namespace libtorrent
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
TORRENT_ASSERT(j->buffer.disk_block == 0); TORRENT_ASSERT(j->buffer.disk_block == 0);
if (m_settings.get_int(settings_pack::cache_size) == 0 if (m_settings.get_int(settings_pack::cache_size) == 0
|| m_settings.get_bool(settings_pack::use_read_cache) == false) || m_settings.get_bool(settings_pack::use_read_cache) == false)
return 0; return 0;
@ -3463,7 +3463,7 @@ namespace libtorrent
if (j->action == disk_io_job::read if (j->action == disk_io_job::read
&& m_settings.get_bool(settings_pack::use_read_cache) && m_settings.get_bool(settings_pack::use_read_cache)
&& m_settings.get_int(settings_pack::cache_size) > 0) && m_settings.get_int(settings_pack::cache_size) != 0)
{ {
int state = prep_read_job_impl(j, false); int state = prep_read_job_impl(j, false);
switch (state) switch (state)

View File

@ -355,10 +355,10 @@ namespace libtorrent
// the total number of blocks run through SHA-1 hashing // the total number of blocks run through SHA-1 hashing
METRIC(disk, num_blocks_hashed) METRIC(disk, num_blocks_hashed)
// the number of blocks read from the disk cache // the number of blocks read from the disk cache
METRIC(disk, num_blocks_cache_hits) METRIC(disk, num_blocks_cache_hits)
// the number of disk I/O operation for reads and writes. One disk // the number of disk I/O operation for reads and writes. One disk
// operation may transfer more then one block. // operation may transfer more then one block.
METRIC(disk, num_write_ops) METRIC(disk, num_write_ops)