From 2f627a4b002137c5ee4302358e8be2df443b05bf Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 24 May 2009 16:49:01 +0000 Subject: [PATCH] attempt to mitigate read cache thrashing --- include/libtorrent/disk_io_thread.hpp | 2 +- src/disk_io_thread.cpp | 21 ++++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index 663aa66b6..b9f5ac1c0 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -311,7 +311,7 @@ namespace libtorrent int clear_oldest_read_piece(int num_blocks, cache_t::iterator ignore , mutex_t::scoped_lock& l); int read_into_piece(cached_piece_entry& p, int start_block - , int options, mutex_t::scoped_lock& l); + , int options, int num_blocks, mutex_t::scoped_lock& l); int cache_read_block(disk_io_job const& j, mutex_t::scoped_lock& l); int cache_read_piece(disk_io_job const& j, mutex_t::scoped_lock& l); int free_piece(cached_piece_entry& p, mutex_t::scoped_lock& l); diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index 2ff50675f..36c6e6811 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -760,7 +760,7 @@ namespace libtorrent // fills a piece with data from disk, returns the total number of bytes // read or -1 if there was an error int disk_io_thread::read_into_piece(cached_piece_entry& p, int start_block - , int options, mutex_t::scoped_lock& l) + , int options, int num_blocks, mutex_t::scoped_lock& l) { int piece_size = p.storage->info()->piece_size(p.piece); int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; @@ -784,8 +784,7 @@ namespace libtorrent ++m_cache_stats.read_cache_size; ++end_block; ++num_read; -#error the length should be min(read_cache_line_size, (cache_size - in_use())/2) - if (num_read >= m_settings.read_cache_line_size) break; + if (num_read >= num_blocks) break; } if (end_block == start_block) return -2; @@ -867,6 +866,8 @@ namespace libtorrent // returns -1 on read error, -2 on out of memory error or the number of bytes read // this function ignores the cache size limit, it will read the entire // piece regardless of the offset in j + // this is used for seed-mode, where we need to read the entire piece to calculate + // the hash int disk_io_thread::cache_read_piece(disk_io_job const& j, mutex_t::scoped_lock& l) { INVARIANT_CHECK; @@ -885,7 +886,7 @@ namespace libtorrent p.blocks.reset(new (std::nothrow) char*[blocks_in_piece]); if (!p.blocks) return -1; std::memset(&p.blocks[0], 0, blocks_in_piece * sizeof(char*)); - int ret = read_into_piece(p, 0, ignore_cache_size, l); + int ret = read_into_piece(p, 0, ignore_cache_size, INT_MAX, l); if (ret == -1) free_piece(p, l); @@ -906,7 +907,10 @@ namespace libtorrent int start_block = j.offset / m_block_size; - int blocks_to_read = (std::min)(blocks_in_piece - start_block, m_settings.read_cache_line_size); + int blocks_to_read = blocks_in_piece - start_block; + blocks_to_read = (std::min)(blocks_to_read, (std::max)((m_settings.cache_size + + m_cache_stats.read_cache_size - in_use())/2, 3)); + blocks_to_read = (std::min)(blocks_to_read, m_settings.read_cache_line_size); if (in_use() + blocks_to_read > m_settings.cache_size) if (flush_cache_blocks(l, in_use() + blocks_to_read - m_settings.cache_size @@ -921,7 +925,7 @@ namespace libtorrent p.blocks.reset(new (std::nothrow) char*[blocks_in_piece]); if (!p.blocks) return -1; std::memset(&p.blocks[0], 0, blocks_in_piece * sizeof(char*)); - int ret = read_into_piece(p, start_block, 0, l); + int ret = read_into_piece(p, start_block, 0, blocks_to_read, l); if (ret == -1) free_piece(p, l); @@ -1082,12 +1086,15 @@ namespace libtorrent while (end_block < blocks_in_piece && p->blocks[end_block] == 0) ++end_block; int blocks_to_read = end_block - block; + blocks_to_read = (std::min)(blocks_to_read, (std::max)((m_settings.cache_size + + m_cache_stats.read_cache_size - in_use())/2, 3)); + blocks_to_read = (std::min)(blocks_to_read, m_settings.read_cache_line_size); if (in_use() + blocks_to_read > m_settings.cache_size) if (flush_cache_blocks(l, in_use() + blocks_to_read - m_settings.cache_size , p, dont_flush_write_blocks) == 0) return -2; - int ret = read_into_piece(*p, block, 0, l); + int ret = read_into_piece(*p, block, 0, blocks_to_read, l); hit = false; if (ret < 0) return ret; TORRENT_ASSERT(p->blocks[block]);