perf: optimize the only block case in Cache::writeContiguous() (#4679)

This commit is contained in:
Dmitry Antipov 2023-01-30 21:04:40 +03:00 committed by GitHub
parent 18277a6dd0
commit 52d49b84eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 23 additions and 14 deletions

View File

@ -71,21 +71,30 @@ std::pair<Cache::CIter, Cache::CIter> Cache::findContiguous(CIter const begin, C
int Cache::writeContiguous(CIter const begin, CIter const end) const
{
// join the blocks together into contiguous memory `buf`
// The most common case without an extra data copy.
auto const* towrite = begin->buf.get();
// Contiguous area to join more than one block, if any.
auto buf = std::vector<uint8_t>{};
auto const buflen = std::accumulate(
begin,
end,
size_t{},
[](size_t sum, auto const& block) { return sum + std::size(*block.buf); });
buf.reserve(buflen);
for (auto iter = begin; iter != end; ++iter)
if (end - begin > 1)
{
TR_ASSERT(begin->key.first == iter->key.first);
TR_ASSERT(begin->key.second + std::distance(begin, iter) == iter->key.second);
buf.insert(std::end(buf), std::begin(*iter->buf), std::end(*iter->buf));
// Yes, there are.
auto const buflen = std::accumulate(
begin,
end,
size_t{},
[](size_t sum, auto const& block) { return sum + std::size(*block.buf); });
buf.reserve(buflen);
for (auto iter = begin; iter != end; ++iter)
{
TR_ASSERT(begin->key.first == iter->key.first);
TR_ASSERT(begin->key.second + std::distance(begin, iter) == iter->key.second);
buf.insert(std::end(buf), std::begin(*iter->buf), std::end(*iter->buf));
}
TR_ASSERT(std::size(buf) == buflen);
towrite = &buf;
}
TR_ASSERT(std::size(buf) == buflen);
// save it
auto const& [torrent_id, block] = begin->key;
@ -97,13 +106,13 @@ int Cache::writeContiguous(CIter const begin, CIter const end) const
auto const loc = tor->blockLoc(block);
if (auto const err = tr_ioWrite(tor, loc, std::size(buf), std::data(buf)); err != 0)
if (auto const err = tr_ioWrite(tor, loc, std::size(*towrite), std::data(*towrite)); err != 0)
{
return err;
}
++disk_writes_;
disk_write_bytes_ += std::size(buf);
disk_write_bytes_ += std::size(*towrite);
return {};
}