mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 03:52:49 +01:00
Merge bitcoin/bitcoin#24852: util: optimize HexStr
5e61532e72c1021fda9c7b213bd9cf397cb3a802 util: optimizes HexStr (Martin Leitner-Ankerl) 4e2b99f72a90b956f3050095abed4949aff9b516 bench: Adds a benchmark for HexStr (Martin Leitner-Ankerl) 67c8411c37b483caa2fe3f7f4f40b68ed2a9bcf7 test: Adds a test for HexStr that checks all 256 bytes (Martin Leitner-Ankerl) Pull request description: In my benchmark, this rewrite improves runtime 27% (g++) to 46% (clang++) for the benchmark `HexStrBench`: g++ 11.2.0 | ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark |--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:---------- | 0.94 | 1,061,381,310.36 | 0.7% | 12.00 | 3.01 | 3.990 | 1.00 | 0.0% | 0.01 | `HexStrBench` master | 0.68 | 1,465,366,544.25 | 1.7% | 6.00 | 2.16 | 2.778 | 1.00 | 0.0% | 0.01 | `HexStrBench` branch clang++ 13.0.1 | ns/byte | byte/s | err% | ins/byte | cyc/byte | IPC | bra/byte | miss% | total | benchmark |--------------------:|--------------------:|--------:|----------------:|----------------:|-------:|---------------:|--------:|----------:|:---------- | 0.80 | 1,244,713,415.92 | 0.9% | 10.00 | 2.56 | 3.913 | 0.50 | 0.0% | 0.01 | `HexStrBench` master | 0.43 | 2,324,188,940.72 | 0.2% | 4.00 | 1.37 | 2.914 | 0.25 | 0.0% | 0.01 | `HexStrBench` branch Note that the idea for this change comes from denis2342 in #23364. This is a rewrite so no unaligned accesses occur. Also, the lookup table is now calculated at compile time, which hopefully makes the code a bit easier to review. ACKs for top commit: laanwj: Code review ACK 5e61532e72c1021fda9c7b213bd9cf397cb3a802 aureleoules: tACK 5e61532e72c1021fda9c7b213bd9cf397cb3a802. theStack: ACK 5e61532e72c1021fda9c7b213bd9cf397cb3a802 🚤 Tree-SHA512: 40b53d5908332473ef24918d3a80ad1292b60566c02585fa548eb4c3189754971be5a70325f4968fce6d714df898b52d9357aba14d4753a8c70e6ffd273a2319
This commit is contained in:
parent
1288494d4a
commit
e4f8b7097d
@ -44,6 +44,7 @@ bench_bench_dash_SOURCES = \
|
|||||||
bench/pool.cpp \
|
bench/pool.cpp \
|
||||||
bench/rpc_blockchain.cpp \
|
bench/rpc_blockchain.cpp \
|
||||||
bench/rpc_mempool.cpp \
|
bench/rpc_mempool.cpp \
|
||||||
|
bench/strencodings.cpp \
|
||||||
bench/util_time.cpp \
|
bench/util_time.cpp \
|
||||||
bench/base58.cpp \
|
bench/base58.cpp \
|
||||||
bench/bech32.cpp \
|
bench/bech32.cpp \
|
||||||
|
18
src/bench/strencodings.cpp
Normal file
18
src/bench/strencodings.cpp
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright (c) 2022 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <bench/bench.h>
|
||||||
|
#include <bench/data.h>
|
||||||
|
#include <util/strencodings.h>
|
||||||
|
|
||||||
|
static void HexStrBench(benchmark::Bench& bench)
|
||||||
|
{
|
||||||
|
auto const& data = benchmark::data::block813851;
|
||||||
|
bench.batch(data.size()).unit("byte").run([&] {
|
||||||
|
auto hex = HexStr(data);
|
||||||
|
ankerl::nanobench::doNotOptimizeAway(hex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
BENCHMARK(HexStrBench);
|
@ -206,6 +206,24 @@ BOOST_AUTO_TEST_CASE(util_HexStr)
|
|||||||
BOOST_CHECK_EQUAL(HexStr(in_s), out_exp);
|
BOOST_CHECK_EQUAL(HexStr(in_s), out_exp);
|
||||||
BOOST_CHECK_EQUAL(HexStr(in_b), out_exp);
|
BOOST_CHECK_EQUAL(HexStr(in_b), out_exp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto input = std::string();
|
||||||
|
for (size_t i=0; i<256; ++i) {
|
||||||
|
input.push_back(static_cast<char>(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto hex = HexStr(input);
|
||||||
|
BOOST_TEST_REQUIRE(hex.size() == 512);
|
||||||
|
static constexpr auto hexmap = std::string_view("0123456789abcdef");
|
||||||
|
for (size_t i = 0; i < 256; ++i) {
|
||||||
|
auto upper = hexmap.find(hex[i * 2]);
|
||||||
|
auto lower = hexmap.find(hex[i * 2 + 1]);
|
||||||
|
BOOST_TEST_REQUIRE(upper != std::string_view::npos);
|
||||||
|
BOOST_TEST_REQUIRE(lower != std::string_view::npos);
|
||||||
|
BOOST_TEST_REQUIRE(i == upper*16 + lower);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(span_write_bytes)
|
BOOST_AUTO_TEST_CASE(span_write_bytes)
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <tinyformat.h>
|
#include <tinyformat.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@ -493,17 +494,37 @@ std::string Capitalize(std::string str)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using ByteAsHex = std::array<char, 2>;
|
||||||
|
|
||||||
|
constexpr std::array<ByteAsHex, 256> CreateByteToHexMap()
|
||||||
|
{
|
||||||
|
constexpr char hexmap[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
|
||||||
|
std::array<ByteAsHex, 256> byte_to_hex{};
|
||||||
|
for (size_t i = 0; i < byte_to_hex.size(); ++i) {
|
||||||
|
byte_to_hex[i][0] = hexmap[i >> 4];
|
||||||
|
byte_to_hex[i][1] = hexmap[i & 15];
|
||||||
|
}
|
||||||
|
return byte_to_hex;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
std::string HexStr(const Span<const uint8_t> s)
|
std::string HexStr(const Span<const uint8_t> s)
|
||||||
{
|
{
|
||||||
std::string rv(s.size() * 2, '\0');
|
std::string rv(s.size() * 2, '\0');
|
||||||
static constexpr char hexmap[16] = { '0', '1', '2', '3', '4', '5', '6', '7',
|
static constexpr auto byte_to_hex = CreateByteToHexMap();
|
||||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
static_assert(sizeof(byte_to_hex) == 512);
|
||||||
auto it = rv.begin();
|
|
||||||
|
char* it = rv.data();
|
||||||
for (uint8_t v : s) {
|
for (uint8_t v : s) {
|
||||||
*it++ = hexmap[v >> 4];
|
std::memcpy(it, byte_to_hex[v].data(), 2);
|
||||||
*it++ = hexmap[v & 15];
|
it += 2;
|
||||||
}
|
}
|
||||||
assert(it == rv.end());
|
|
||||||
|
assert(it == rv.data() + rv.size());
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user