diff --git a/docs/manual.rst b/docs/manual.rst index 243450d81..87066e660 100644 --- a/docs/manual.rst +++ b/docs/manual.rst @@ -715,6 +715,7 @@ Returns status of the disk cache for this session. size_type reads; int cache_size; int read_cache_size; + int total_used_buffers; }; ``blocks_written`` is the total number of 16 KiB blocks written to disk @@ -740,6 +741,10 @@ This includes both read and write cache. ``read_cache_size`` is the number of 16KiB blocks in the read cache. +``total_used_buffers`` is the total number of buffers currently in use. +This includes the read/write disk cache as well as send and receive buffers +used in peer connections. + get_cache_info() ---------------- diff --git a/examples/client_test.cpp b/examples/client_test.cpp index 190ea5af9..918514b8a 100644 --- a/examples/client_test.cpp +++ b/examples/client_test.cpp @@ -699,6 +699,7 @@ int main(int argc, char* argv[]) " -t sets the scan interval of the monitor dir\n" " -x loads an emule IP-filter file\n" " -c sets the max number of connections\n" + " -C sets the max cache size. Specified in 16kB blocks\n" "\n\n" "TORRENT is a path to a .torrent file\n" "MAGNETURL is a magnet: url\n" @@ -895,6 +896,7 @@ int main(int argc, char* argv[]) } break; case 'c': ses.set_max_connections(atoi(arg)); break; + case 'C': settings.cache_size = atoi(arg); break; } ++i; // skip the argument } @@ -1286,7 +1288,8 @@ int main(int argc, char* argv[]) " write cache hits: " << ((cs.blocks_written - cs.writes) * 100 / cs.blocks_written) << "% " " read cache hits: " << (cs.blocks_read_hit * 100 / cs.blocks_read) << "% " " cache size: " << add_suffix(cs.cache_size * 16 * 1024) - << " (" << add_suffix(cs.read_cache_size * 16 * 1024) << ")" + << " (" << add_suffix(cs.read_cache_size * 16 * 1024) << ") / " + << add_suffix(cs.total_used_buffers * 16 * 1024) << " ====\n" "==== optimistic unchoke: " << sess_stat.optimistic_unchoke_counter << " unchoke counter: " << sess_stat.unchoke_counter diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index 76369dd98..238d5364e 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -134,6 +134,7 @@ namespace libtorrent , reads(0) , cache_size(0) , read_cache_size(0) + , total_used_buffers(0) {} // the number of 16kB blocks written @@ -156,6 +157,10 @@ namespace libtorrent // the number of blocks in the cache used for read cache int read_cache_size; + + // the total number of blocks that are currently in use + // this includes send and receive buffers + mutable int total_used_buffers; }; struct disk_buffer_pool : boost::noncopyable @@ -294,6 +299,7 @@ namespace libtorrent void free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l); bool make_room(int num_blocks , cache_t::iterator ignore + , bool flush_write_cache , mutex_t::scoped_lock& l); int try_read_from_cache(disk_io_job const& j); int read_piece_from_cache_and_hash(disk_io_job const& j, sha1_hash& h); diff --git a/parse_disk_buffer_log.py b/parse_disk_buffer_log.py index 4eaed2212..b0771e3e1 100755 --- a/parse_disk_buffer_log.py +++ b/parse_disk_buffer_log.py @@ -2,51 +2,51 @@ import os, sys, time -#lines = open(sys.argv[1], 'rb').readlines() -# -## logfile format: -## : -## example: -## 16434 read cache: 17 -# -#keys = [] -#fields = {} -#maximum = {} -#out = open('disk_buffer_log.dat', 'w+') -# -#last_t = 0 -#for l in lines: -# try: -# t = int(l[0:l.find(' ')]) -# c = l[l.find(' ')+1:l.find(':')] -# n = int(l[l.find(':')+1:-1]) -# except: -# print l -# continue -# -# if last_t != t: -# print >>out, '%d\t' % last_t, -# for i in keys: -# print >>out, '%d\t' % maximum[i], -# print >>out, '\n', -# -# if not c in keys: -# keys.append(c) -# fields[c] = 0 -# maximum[c] = 0 -# -# fields[c] = n -# if n > maximum[c]: maximum[c] = n -# -# if last_t != t: -# last_t = t -# maximum = fields -# -#for i in keys: -# print i, -#print -# -#out.close() +lines = open(sys.argv[1], 'rb').readlines() + +# logfile format: +# : +# example: +# 16434 read cache: 17 + +keys = [] +fields = {} +maximum = {} +out = open('disk_buffer_log.dat', 'w+') + +last_t = 0 +for l in lines: + try: + t = int(l[0:l.find(' ')]) + c = l[l.find(' ')+1:l.find(':')] + n = int(l[l.find(':')+1:-1]) + except: + print l + continue + + if last_t != t: + print >>out, '%d\t' % last_t, + for i in keys: + print >>out, '%d\t' % maximum[i], + print >>out, '\n', + + if not c in keys: + keys.append(c) + fields[c] = 0 + maximum[c] = 0 + + fields[c] = n + if n > maximum[c]: maximum[c] = n + + if last_t != t: + last_t = t + maximum = fields + +for i in keys: + print i, +print + +out.close() keys = ['check piece', 'send buffer', 'read cache', 'receive buffer', 'hash temp'] diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 90e3b4f72..b399458c1 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -279,6 +279,7 @@ namespace libtorrent cache_status disk_io_thread::status() const { mutex_t::scoped_lock l(m_piece_mutex); + m_cache_stats.total_used_buffers = in_use(); return m_cache_stats; } @@ -573,7 +574,7 @@ namespace libtorrent int end_block = start_block; for (int i = start_block; i < blocks_in_piece && (in_use() < m_settings.cache_size - || (options && ignore_cache_size)); ++i) + || (options & ignore_cache_size)); ++i) { // this is a block that is already allocated // stop allocating and don't read more than @@ -655,13 +656,25 @@ namespace libtorrent bool disk_io_thread::make_room(int num_blocks , cache_t::iterator ignore + , bool flush_write_cache , mutex_t::scoped_lock& l) { - if (m_settings.cache_size - in_use() < num_blocks) + while (m_settings.cache_size - in_use() < num_blocks) { // there's not enough room in the cache, clear a piece // from the read cache - if (!clear_oldest_read_piece(ignore, l)) return false; + if (!clear_oldest_read_piece(ignore, l)) break; + } + + // try flushing write cache + while (flush_write_cache && m_settings.cache_size - in_use() < num_blocks) + { + cache_t::iterator i = std::min_element( + m_pieces.begin(), m_pieces.end() + , bind(&cached_piece_entry::last_use, _1) + < bind(&cached_piece_entry::last_use, _2)); + if (i == m_pieces.end()) break; + flush_and_remove(i, l); } return m_settings.cache_size - in_use() >= num_blocks; @@ -677,7 +690,7 @@ namespace libtorrent int piece_size = j.storage->info()->piece_size(j.piece); int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; - make_room(blocks_in_piece, m_read_pieces.end(), l); + make_room(blocks_in_piece, m_read_pieces.end(), true, l); cached_piece_entry p; p.piece = j.piece; @@ -708,7 +721,7 @@ namespace libtorrent int start_block = j.offset / m_block_size; if (!make_room(blocks_in_piece - start_block - , m_read_pieces.end(), l)) return -2; + , m_read_pieces.end(), false, l)) return -2; cached_piece_entry p; p.piece = j.piece; @@ -869,7 +882,7 @@ namespace libtorrent int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; int end_block = block; while (end_block < blocks_in_piece && p->blocks[end_block] == 0) ++end_block; - if (!make_room(end_block - block, p, l)) return -2; + if (!make_room(end_block - block, p, false, l)) return -2; int ret = read_into_piece(*p, block, 0, l); hit = false; if (ret < 0) return ret;