From f9ec9180ffed5ffd9325dadc64a9e9e8f521cadd Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Sun, 16 May 2010 23:14:47 +0000 Subject: [PATCH] more disk cache cleanup optimizations --- include/libtorrent/disk_io_thread.hpp | 2 +- src/disk_io_thread.cpp | 40 +++++++++++++++++++++------ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/include/libtorrent/disk_io_thread.hpp b/include/libtorrent/disk_io_thread.hpp index 82fd3de18..a26fffbba 100644 --- a/include/libtorrent/disk_io_thread.hpp +++ b/include/libtorrent/disk_io_thread.hpp @@ -395,7 +395,7 @@ namespace libtorrent , int options, int num_blocks, mutex::scoped_lock& l); int cache_read_block(disk_io_job const& j, mutex::scoped_lock& l); int free_piece(cached_piece_entry& p, mutex::scoped_lock& l); - void drain_piece_bufs(cached_piece_entry& p, std::vector& buf + int drain_piece_bufs(cached_piece_entry& p, std::vector& buf , mutex::scoped_lock& l); int try_read_from_cache(disk_io_job const& j, bool& hit); int read_piece_from_cache_and_hash(disk_io_job const& j, sha1_hash& h); diff --git a/src/disk_io_thread.cpp b/src/disk_io_thread.cpp index ef8950925..39c82f080 100644 --- a/src/disk_io_thread.cpp +++ b/src/disk_io_thread.cpp @@ -522,21 +522,24 @@ namespace libtorrent if (!bufs.empty()) free_multiple_buffers(&bufs[0], bufs.size()); } - void disk_io_thread::drain_piece_bufs(cached_piece_entry& p, std::vector& buf + int disk_io_thread::drain_piece_bufs(cached_piece_entry& p, std::vector& buf , mutex::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; + int ret = 0; for (int i = 0; i < blocks_in_piece; ++i) { if (p.blocks[i].buf == 0) continue; buf.push_back(p.blocks[i].buf); + ++ret; p.blocks[i].buf = 0; --p.num_blocks; --m_cache_stats.cache_size; --m_cache_stats.read_cache_size; } + return ret; } // returns the number of blocks that were freed @@ -546,16 +549,20 @@ namespace libtorrent int blocks_in_piece = (piece_size + m_block_size - 1) / m_block_size; int ret = 0; + // build a vector of all the buffers we need to free + // and free them all in one go + std::vector buffers; for (int i = 0; i < blocks_in_piece; ++i) { if (p.blocks[i].buf == 0) continue; - free_buffer(p.blocks[i].buf); + buffers.push_back(p.blocks[i].buf); ++ret; p.blocks[i].buf = 0; --p.num_blocks; --m_cache_stats.cache_size; --m_cache_stats.read_cache_size; } + if (!buffers.empty()) free_multiple_buffers(&buffers[0], buffers.size()); return ret; } @@ -578,9 +585,13 @@ namespace libtorrent // don't replace an entry that is is too young if (time_now() > i->expire) return 0; int blocks = 0; + + // build a vector of all the buffers we need to free + // and free them all in one go + std::vector buffers; if (num_blocks >= i->num_blocks) { - blocks = free_piece(const_cast(*i), l); + blocks = drain_piece_bufs(const_cast(*i), buffers, l); } else { @@ -598,7 +609,7 @@ namespace libtorrent { while (i->blocks[start].buf == 0 && start <= end) ++start; if (start > end) break; - free_buffer(i->blocks[start].buf); + buffers.push_back(i->blocks[start].buf); i->blocks[start].buf = 0; ++blocks; --const_cast(*i).num_blocks; @@ -610,7 +621,7 @@ namespace libtorrent while (i->blocks[end].buf == 0 && start <= end) --end; if (start > end) break; - free_buffer(i->blocks[end].buf); + buffers.push_back(i->blocks[end].buf); i->blocks[end].buf = 0; ++blocks; --const_cast(*i).num_blocks; @@ -618,9 +629,10 @@ namespace libtorrent --m_cache_stats.read_cache_size; --num_blocks; } - } if (i->num_blocks == 0) idx.erase(i); + + if (!buffers.empty()) free_multiple_buffers(&buffers[0], buffers.size()); return blocks; } @@ -805,18 +817,20 @@ namespace libtorrent j.buffer = 0; j.piece = p.piece; test_error(j); + std::vector buffers; for (int i = start; i < end; ++i) { if (p.blocks[i].buf == 0) continue; j.buffer_size = (std::min)(piece_size - i * m_block_size, m_block_size); int result = j.error ? -1 : j.buffer_size; j.offset = i * m_block_size; - free_buffer(p.blocks[i].buf); + buffers.push_back(p.blocks[i].buf); post_callback(p.blocks[i].callback, j, result); p.blocks[i].callback.clear(); p.blocks[i].buf = 0; ++ret; } + if (!buffers.empty()) free_multiple_buffers(&buffers[0], buffers.size()); TORRENT_ASSERT(buffer_size == 0); // std::cerr << " flushing p: " << p.piece << " cached_blocks: " << m_cache_stats.cache_size << std::endl; @@ -1311,6 +1325,9 @@ namespace libtorrent TORRENT_ASSERT(p.blocks[block].buf); } + // build a vector of all the buffers we need to free + // and free them all in one go + std::vector buffers; while (size > 0) { TORRENT_ASSERT(p.blocks[block].buf); @@ -1331,7 +1348,7 @@ namespace libtorrent // the peer skipped for (int i = block; i >= 0 && p.blocks[i].buf; --i) { - free_buffer(p.blocks[i].buf); + buffers.push_back(p.blocks[i].buf); p.blocks[i].buf = 0; --p.num_blocks; --m_cache_stats.cache_size; @@ -1340,6 +1357,7 @@ namespace libtorrent } ++block; } + if (!buffers.empty()) free_multiple_buffers(&buffers[0], buffers.size()); return j.buffer_size; } @@ -2220,6 +2238,9 @@ namespace libtorrent cache_piece_index_t::iterator start = idx.lower_bound(std::pair(j.storage.get(), 0)); cache_piece_index_t::iterator end = idx.upper_bound(std::pair(j.storage.get(), INT_MAX)); + // build a vector of all the buffers we need to free + // and free them all in one go + std::vector buffers; for (cache_piece_index_t::iterator i = start; i != end; ++i) { torrent_info const& ti = *i->storage->info(); @@ -2227,13 +2248,14 @@ namespace libtorrent for (int j = 0; j < blocks_in_piece; ++j) { if (i->blocks[j].buf == 0) continue; - free_buffer(i->blocks[j].buf); + buffers.push_back(i->blocks[j].buf); i->blocks[j].buf = 0; --m_cache_stats.cache_size; } } idx.erase(start, end); l.unlock(); + if (!buffers.empty()) free_multiple_buffers(&buffers[0], buffers.size()); release_memory(); ret = j.storage->delete_files_impl();