perf: avoid string allocations by using fixed-width hash strings (#5725)
This commit is contained in:
parent
0bb222b2cb
commit
0a6d1806f9
|
@ -25,6 +25,7 @@ extern "C"
|
|||
|
||||
#include "libtransmission/crypto-utils.h"
|
||||
#include "libtransmission/tr-assert.h"
|
||||
#include "libtransmission/tr-strbuf.h"
|
||||
#include "libtransmission/utils.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
@ -150,24 +151,16 @@ namespace
|
|||
namespace hex_impl
|
||||
{
|
||||
|
||||
constexpr void tr_binary_to_hex(void const* vinput, void* voutput, size_t byte_length)
|
||||
template<typename InIt, typename OutIt>
|
||||
constexpr void tr_binary_to_hex(InIt begin, InIt end, OutIt out)
|
||||
{
|
||||
auto constexpr Hex = "0123456789abcdef"sv;
|
||||
|
||||
auto const* input = static_cast<uint8_t const*>(vinput);
|
||||
auto* output = static_cast<char*>(voutput);
|
||||
|
||||
/* go from back to front to allow for in-place conversion */
|
||||
input += byte_length;
|
||||
output += byte_length * 2;
|
||||
|
||||
*output = '\0';
|
||||
|
||||
while (byte_length-- > 0)
|
||||
while (begin != end)
|
||||
{
|
||||
unsigned int const val = *(--input);
|
||||
*(--output) = Hex[val & 0xf];
|
||||
*(--output) = Hex[val >> 4];
|
||||
auto const val = static_cast<unsigned int>(*begin++);
|
||||
*out++ = Hex[val >> 4];
|
||||
*out++ = Hex[val & 0xF];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,21 +181,23 @@ constexpr void tr_hex_to_binary(char const* input, void* voutput, size_t byte_le
|
|||
} // namespace hex_impl
|
||||
} // namespace
|
||||
|
||||
std::string tr_sha1_to_string(tr_sha1_digest_t const& digest)
|
||||
tr_sha1_string tr_sha1_to_string(tr_sha1_digest_t const& digest)
|
||||
{
|
||||
using namespace hex_impl;
|
||||
|
||||
auto str = std::string(std::size(digest) * 2, '?');
|
||||
tr_binary_to_hex(digest.data(), str.data(), std::size(digest));
|
||||
auto str = tr_sha1_string{};
|
||||
tr_binary_to_hex(std::begin(digest), std::end(digest), std::back_inserter(str));
|
||||
TR_ASSERT(std::size(str) == TrSha1DigestStrlen);
|
||||
return str;
|
||||
}
|
||||
|
||||
std::string tr_sha256_to_string(tr_sha256_digest_t const& digest)
|
||||
tr_sha256_string tr_sha256_to_string(tr_sha256_digest_t const& digest)
|
||||
{
|
||||
using namespace hex_impl;
|
||||
|
||||
auto str = std::string(std::size(digest) * 2, '?');
|
||||
tr_binary_to_hex(digest.data(), str.data(), std::size(digest));
|
||||
auto str = tr_sha256_string{};
|
||||
tr_binary_to_hex(std::begin(digest), std::end(digest), std::back_inserter(str));
|
||||
TR_ASSERT(std::size(str) == TrSha256DigestStrlen);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,9 @@
|
|||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
#include "transmission.h" // tr_sha1_digest_t
|
||||
#include "libtransmission/transmission.h" // tr_sha1_digest_t
|
||||
|
||||
#include "libtransmission/tr-strbuf.h"
|
||||
|
||||
/**
|
||||
* @addtogroup utils Utilities
|
||||
|
@ -133,20 +135,24 @@ T tr_rand_obj()
|
|||
*/
|
||||
[[nodiscard]] std::string tr_base64_decode(std::string_view input);
|
||||
|
||||
using tr_sha1_string = tr_strbuf<char, sizeof(tr_sha1_digest_t) * 2U + 1U>;
|
||||
|
||||
/**
|
||||
* @brief Generate an ascii hex string for a sha1 digest.
|
||||
*/
|
||||
[[nodiscard]] std::string tr_sha1_to_string(tr_sha1_digest_t const&);
|
||||
[[nodiscard]] tr_sha1_string tr_sha1_to_string(tr_sha1_digest_t const&);
|
||||
|
||||
/**
|
||||
* @brief Generate a sha1 digest from a hex string.
|
||||
*/
|
||||
[[nodiscard]] std::optional<tr_sha1_digest_t> tr_sha1_from_string(std::string_view hex);
|
||||
|
||||
using tr_sha256_string = tr_strbuf<char, sizeof(tr_sha256_digest_t) * 2U + 1U>;
|
||||
|
||||
/**
|
||||
* @brief Generate an ascii hex string for a sha256 digest.
|
||||
*/
|
||||
[[nodiscard]] std::string tr_sha256_to_string(tr_sha256_digest_t const&);
|
||||
[[nodiscard]] tr_sha256_string tr_sha256_to_string(tr_sha256_digest_t const&);
|
||||
|
||||
/**
|
||||
* @brief Generate a sha256 digest from a hex string.
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "transmission.h"
|
||||
|
||||
#include "announce-list.h"
|
||||
#include "crypto-utils.h"
|
||||
#include "tr-strbuf.h" // tr_urlbuf
|
||||
#include "utils.h" // tr_strv_convert_utf8()
|
||||
|
||||
|
@ -58,12 +59,12 @@ public:
|
|||
return announce_list_;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::string const& info_hash_string() const noexcept
|
||||
[[nodiscard]] constexpr auto const& info_hash_string() const noexcept
|
||||
{
|
||||
return info_hash_str_;
|
||||
}
|
||||
|
||||
[[nodiscard]] constexpr std::string const& info_hash2_string() const noexcept
|
||||
[[nodiscard]] constexpr auto const& info_hash2_string() const noexcept
|
||||
{
|
||||
return info_hash2_str_;
|
||||
}
|
||||
|
@ -80,7 +81,7 @@ protected:
|
|||
std::vector<std::string> webseed_urls_;
|
||||
tr_sha1_digest_t info_hash_ = {};
|
||||
tr_sha256_digest_t info_hash2_ = {};
|
||||
std::string info_hash_str_;
|
||||
std::string info_hash2_str_;
|
||||
tr_sha1_string info_hash_str_;
|
||||
tr_sha256_string info_hash2_str_;
|
||||
std::string name_;
|
||||
};
|
||||
|
|
|
@ -33,8 +33,16 @@ public:
|
|||
ensure_sz();
|
||||
}
|
||||
|
||||
tr_strbuf(tr_strbuf const& other) = delete;
|
||||
tr_strbuf& operator=(tr_strbuf const& other) = delete;
|
||||
tr_strbuf(tr_strbuf const& other)
|
||||
{
|
||||
assign(other.sv());
|
||||
}
|
||||
|
||||
tr_strbuf& operator=(tr_strbuf const& other)
|
||||
{
|
||||
assign(other.sv());
|
||||
return *this;
|
||||
}
|
||||
|
||||
tr_strbuf(tr_strbuf&& other)
|
||||
: buffer_{ std::move(other.buffer_) }
|
||||
|
|
|
@ -43,7 +43,8 @@ QString getNameFromMagnet(QString const& magnet)
|
|||
return QString::fromStdString(tmp.name());
|
||||
}
|
||||
|
||||
return QString::fromStdString(tmp.info_hash_string());
|
||||
auto const& hashstr = tmp.info_hash_string();
|
||||
return QString::fromUtf8(std::data(hashstr), std::size(hashstr));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
11
qt/Torrent.h
11
qt/Torrent.h
|
@ -105,6 +105,7 @@ class TorrentHash
|
|||
{
|
||||
private:
|
||||
tr_sha1_digest_t data_ = {};
|
||||
QString data_str_;
|
||||
|
||||
public:
|
||||
TorrentHash() = default;
|
||||
|
@ -119,6 +120,9 @@ public:
|
|||
if (auto const hash = tr_sha1_from_string(str != nullptr ? str : ""); hash)
|
||||
{
|
||||
data_ = *hash;
|
||||
|
||||
auto const tmpstr = tr_sha1_to_string(data_);
|
||||
data_str_ = QString::fromUtf8(std::data(tmpstr), std::size(tmpstr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,6 +131,9 @@ public:
|
|||
if (auto const hash = tr_sha1_from_string(str.toStdString()); hash)
|
||||
{
|
||||
data_ = *hash;
|
||||
|
||||
auto const tmpstr = tr_sha1_to_string(data_);
|
||||
data_str_ = QString::fromUtf8(std::data(tmpstr), std::size(tmpstr));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,9 +152,9 @@ public:
|
|||
return data_ < that.data_;
|
||||
}
|
||||
|
||||
QString toString() const
|
||||
[[nodiscard]] constexpr auto& toString() const noexcept
|
||||
{
|
||||
return QString::fromStdString(tr_sha1_to_string(data_));
|
||||
return data_str_;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue