1
0
Fork 0
mirror of https://github.com/transmission/transmission synced 2025-03-03 18:25:35 +00:00

perf: in cache, flush biggest contiguous blocks (#5671)

This commit is contained in:
Charles Kerr 2023-06-27 12:08:29 -05:00 committed by GitHub
parent 24bc3d135d
commit 2db2091599
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 57 deletions

View file

@ -22,52 +22,45 @@
#include "libtransmission/torrent.h"
#include "libtransmission/torrents.h"
#include "libtransmission/tr-assert.h"
#include "libtransmission/utils.h" // tr_time(), tr_formatter
#include "libtransmission/utils.h" // tr_formatter
Cache::Key Cache::make_key(tr_torrent const* torrent, tr_block_info::Location loc) noexcept
{
return std::make_pair(torrent->id(), loc.block);
}
std::pair<Cache::CIter, Cache::CIter> Cache::find_contiguous(CIter const begin, CIter const end, CIter const iter) noexcept
Cache::CIter Cache::find_span_end(CIter span_begin, CIter end) noexcept
{
if (iter == end)
static constexpr auto NotAdjacent = [](CacheBlock const& block1, CacheBlock const& block2)
{
return std::make_pair(end, end);
return block1.key.first != block2.key.first || block1.key.second + 1 != block2.key.second;
};
auto const span_end = std::adjacent_find(span_begin, end, NotAdjacent);
return span_end == end ? end : std::next(span_end);
}
std::pair<Cache::CIter, Cache::CIter> Cache::find_biggest_span(CIter const begin, CIter const end) noexcept
{
auto biggest_begin = begin;
auto biggest_end = begin;
auto biggest_len = std::distance(biggest_begin, biggest_end);
for (auto span_begin = begin; span_begin < end;)
{
auto span_end = find_span_end(span_begin, end);
auto const len = std::distance(span_begin, span_end);
if (len > biggest_len)
{
biggest_begin = span_begin;
biggest_end = span_end;
biggest_len = len;
}
std::advance(span_begin, len);
}
auto span_begin = iter;
for (auto key = iter->key;;)
{
if (span_begin == begin)
{
break;
}
--key.second;
auto const prev = std::prev(span_begin);
if (prev->key != key)
{
break;
}
}
auto span_end = std::next(iter);
for (auto key = iter->key;;)
{
if (span_end == end)
{
break;
}
++key.second;
if (span_end->key != key)
{
break;
}
}
return std::make_pair(span_begin, span_end);
return { biggest_begin, biggest_end };
}
int Cache::write_contiguous(CIter const begin, CIter const end) const
@ -153,8 +146,6 @@ int Cache::write_block(tr_torrent_id_t tor_id, tr_block_index_t block, std::uniq
iter->key = key;
}
iter->time_added = tr_time();
iter->buf = std::move(writeme);
++cache_writes_;
@ -203,16 +194,16 @@ int Cache::prefetch_block(tr_torrent* torrent, tr_block_info::Location const& lo
int Cache::flush_span(CIter const begin, CIter const end)
{
for (auto walk = begin; walk < end;)
for (auto span_begin = begin; span_begin < end;)
{
auto const [contig_begin, contig_end] = find_contiguous(begin, end, walk);
auto const span_end = find_span_end(span_begin, end);
if (auto const err = write_contiguous(contig_begin, contig_end); err != 0)
if (auto const err = write_contiguous(span_begin, span_end); err != 0)
{
return err;
}
walk = contig_end;
span_begin = span_end;
}
blocks_.erase(begin, end);
@ -240,20 +231,15 @@ int Cache::flush_torrent(tr_torrent const* torrent)
std::lower_bound(std::begin(blocks_), std::end(blocks_), std::make_pair(tor_id + 1, 0), compare));
}
int Cache::flush_oldest()
int Cache::flush_biggest()
{
auto const oldest = std::min_element(
std::begin(blocks_),
std::end(blocks_),
[](auto const& a, auto const& b) { return a.time_added < b.time_added; });
auto const [begin, end] = find_biggest_span(std::begin(blocks_), std::end(blocks_));
if (oldest == std::end(blocks_)) // nothing to flush
if (begin == end) // nothing to flush
{
return 0;
}
auto const [begin, end] = find_contiguous(std::begin(blocks_), std::end(blocks_), oldest);
if (auto const err = write_contiguous(begin, end); err != 0)
{
return err;
@ -267,7 +253,7 @@ int Cache::cache_trim()
{
while (std::size(blocks_) > max_blocks_)
{
if (auto const err = flush_oldest(); err != 0)
if (auto const err = flush_biggest(); err != 0)
{
return err;
}

View file

@ -11,7 +11,6 @@
#include <cstddef> // for size_t
#include <cstdint> // for intX_t, uintX_t
#include <ctime>
#include <memory> // for std::unique_ptr
#include <utility> // for std::pair
#include <vector>
@ -54,7 +53,6 @@ private:
{
Key key;
std::unique_ptr<BlockData> buf;
time_t time_added = {};
};
using Blocks = std::vector<CacheBlock>;
@ -74,16 +72,18 @@ private:
[[nodiscard]] static Key make_key(tr_torrent const* torrent, tr_block_info::Location loc) noexcept;
[[nodiscard]] static std::pair<CIter, CIter> find_contiguous(CIter const begin, CIter const end, CIter const iter) noexcept;
[[nodiscard]] static std::pair<CIter, CIter> find_biggest_span(CIter begin, CIter end) noexcept;
[[nodiscard]] static CIter find_span_end(CIter span_begin, CIter end) noexcept;
// @return any error code from tr_ioWrite()
[[nodiscard]] int write_contiguous(CIter const begin, CIter const end) const;
[[nodiscard]] int write_contiguous(CIter begin, CIter end) const;
// @return any error code from writeContiguous()
[[nodiscard]] int flush_span(CIter const begin, CIter const end);
[[nodiscard]] int flush_span(CIter begin, CIter end);
// @return any error code from writeContiguous()
[[nodiscard]] int flush_oldest();
[[nodiscard]] int flush_biggest();
// @return any error code from writeContiguous()
[[nodiscard]] int cache_trim();