Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmake/XrplAddBenchmark.cmake
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
include_guard()

include(isolate_headers)

# Define a benchmark executable for the module `name`.
Expand Down
39 changes: 20 additions & 19 deletions src/benchmarks/libxrpl/nodestore/Backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,22 @@
namespace xrpl::node_store {
namespace {

constexpr std::size_t kPoolSizes[] = {1000, 10000, 100000};
constexpr int kThreadCounts[] = {1, 4, 8};
constexpr auto kPoolSizes = std::to_array<std::size_t>({1000, 10000, 100000});
constexpr auto kThreadCounts = std::to_array<std::size_t>({1, 4, 8});
constexpr std::size_t kBatchSize = 256;
constexpr std::size_t kMissRatio = 5;

constexpr std::string_view kNamePrefix = "BM_Backend_";
constexpr std::string_view kNameSeparator = "/";

struct RunState
{
std::unique_ptr<BackendHarness> harness;
Batch present; // prefix-1 objects, eligible to be stored
Batch recent; // prefix-1 objects in the "future" key space
std::vector<uint256> missing; // prefix-2 keys that are never stored
std::vector<std::size_t> shuffle; // [0, poolSize) permutation for random-like access
std::size_t avgPayload = 0; // mean getData().size() over `present`
std::unique_ptr<BackendHarness> harness; ///< backend under test, rebuilt per run
Batch present; ///< prefix-1 objects, eligible to be stored
Batch recent; ///< prefix-1 objects in the "future" key space
std::vector<uint256> missing; ///< prefix-2 keys that are never stored
std::vector<std::size_t> shuffle; ///< [0, poolSize) permutation for random-like access
std::size_t avgPayload = 0; ///< mean getData().size() over `present`

void
release()
Expand Down Expand Up @@ -85,7 +86,7 @@
},
.iterate =
[](IterateContext const& ctx) {
auto& [rs, backend, index, poolSize] = ctx;
auto const& [rs, backend, index, poolSize] = ctx;

Check warning on line 89 in src/benchmarks/libxrpl/nodestore/Backend.cpp

View check run for this annotation

Codecov / codecov/patch

src/benchmarks/libxrpl/nodestore/Backend.cpp#L89

Added line #L89 was not covered by tests
backend.store(rs.present[index % poolSize]);
},
.reportBytes = true,
Expand All @@ -104,7 +105,7 @@
},
.iterate =
[](IterateContext const& ctx) {
auto& [rs, backend, index, poolSize] = ctx;
auto const& [rs, backend, index, poolSize] = ctx;

Check warning on line 108 in src/benchmarks/libxrpl/nodestore/Backend.cpp

View check run for this annotation

Codecov / codecov/patch

src/benchmarks/libxrpl/nodestore/Backend.cpp#L108

Added line #L108 was not covered by tests
std::shared_ptr<NodeObject> result;
backend.fetch(rs.present[index % poolSize]->getHash(), &result);
benchmark::DoNotOptimize(result);
Expand All @@ -118,7 +119,7 @@
.setup = [](SetupContext const& ctx) { ctx.rs.missing = makeMissingKeys(ctx.poolSize); },
.iterate =
[](IterateContext const& ctx) {
auto& [rs, backend, index, poolSize] = ctx;
auto const& [rs, backend, index, poolSize] = ctx;

Check warning on line 122 in src/benchmarks/libxrpl/nodestore/Backend.cpp

View check run for this annotation

Codecov / codecov/patch

src/benchmarks/libxrpl/nodestore/Backend.cpp#L122

Added line #L122 was not covered by tests
std::shared_ptr<NodeObject> result;
backend.fetch(rs.missing[index % poolSize], &result);
benchmark::DoNotOptimize(result);
Expand All @@ -139,10 +140,10 @@
},
.iterate =
[](IterateContext const& ctx) {
auto& [rs, backend, index, poolSize] = ctx;
auto const& [rs, backend, index, poolSize] = ctx;

Check warning on line 143 in src/benchmarks/libxrpl/nodestore/Backend.cpp

View check run for this annotation

Codecov / codecov/patch

src/benchmarks/libxrpl/nodestore/Backend.cpp#L143

Added line #L143 was not covered by tests
std::shared_ptr<NodeObject> result;
auto const pick = rs.shuffle[index % poolSize];
if (index % 5 == 0)
if (index % kMissRatio == 0)
{
backend.fetch(rs.missing[pick], &result);
}
Expand Down Expand Up @@ -170,7 +171,7 @@
},
.iterate =
[](IterateContext const& ctx) {
auto& [rs, backend, index, poolSize] = ctx;
auto const& [rs, backend, index, poolSize] = ctx;

Check warning on line 174 in src/benchmarks/libxrpl/nodestore/Backend.cpp

View check run for this annotation

Codecov / codecov/patch

src/benchmarks/libxrpl/nodestore/Backend.cpp#L174

Added line #L174 was not covered by tests
auto const slot = index % poolSize;
auto const pick = rs.shuffle[slot];

Expand Down Expand Up @@ -239,7 +240,7 @@
{
auto rs = std::make_shared<RunState>();
auto* b = benchmark::RegisterBenchmark(name, makeRunner(w, cfg, rs));
b->RangeMultiplier(10)->Range(kPoolSizes[0], kPoolSizes[std::size(kPoolSizes) - 1]);
b->RangeMultiplier(10)->Range(kPoolSizes.front(), kPoolSizes.back());
b->Threads(1)->Threads(4)->Threads(8)->UseRealTime();

return;
Expand All @@ -249,14 +250,14 @@
{
for (auto const threads : kThreadCounts)
{
if (poolSize % static_cast<std::size_t>(threads) != 0)
if (poolSize % threads != 0)
continue;

auto rs = std::make_shared<RunState>();
benchmark::RegisterBenchmark(name, makeRunner(w, cfg, rs))
->Arg(poolSize)
->Iterations(poolSize / static_cast<std::size_t>(threads))
->Threads(threads)
->Iterations(poolSize / threads)

Check warning on line 259 in src/benchmarks/libxrpl/nodestore/Backend.cpp

View check run for this annotation

Codecov / codecov/patch

src/benchmarks/libxrpl/nodestore/Backend.cpp#L259

Added line #L259 was not covered by tests
->Threads(static_cast<int>(threads))
->UseRealTime();
}
}
Expand Down Expand Up @@ -289,7 +290,7 @@
rs->harness = std::make_unique<BackendHarness>(cfg);
rs->present = makePool(1, poolSize);
rs->avgPayload = averagePayload(rs->present);
std::vector<Batch> const batches = sliceBatches(rs->present, kBatchSize);
std::vector<Batch> const batches = slicePreciseBatches(rs->present, kBatchSize);
if (batches.empty())
{
state.SkipWithError("pool smaller than one batch");
Expand Down
31 changes: 12 additions & 19 deletions src/benchmarks/libxrpl/nodestore/NodeStoreBench.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <memory>
#include <numeric>
#include <random>
#include <ranges>
#include <string>
#include <utility>
#include <vector>
Expand All @@ -40,18 +41,13 @@
rngcpy(void* buffer, std::size_t bytes, Generator& g)
{
using result_type = typename Generator::result_type;
while (bytes >= sizeof(result_type))
while (bytes > 0)
{
auto const v = g();
std::memcpy(buffer, &v, sizeof(v));
buffer = reinterpret_cast<std::uint8_t*>(buffer) + sizeof(v);
bytes -= sizeof(v);
}

if (bytes > 0)
{
auto const v = g();
std::memcpy(buffer, &v, bytes);
auto const chunk = std::min(bytes, sizeof(result_type));
std::memcpy(buffer, &v, chunk);
buffer = reinterpret_cast<std::uint8_t*>(buffer) + chunk;
bytes -= chunk;

Check warning on line 50 in src/benchmarks/libxrpl/nodestore/NodeStoreBench.h

View check run for this annotation

Codecov / codecov/patch

src/benchmarks/libxrpl/nodestore/NodeStoreBench.h#L47-L50

Added lines #L47 - L50 were not covered by tests
}
}

Expand Down Expand Up @@ -145,7 +141,7 @@
Sequence seq(prefix);
Batch pool;
pool.reserve(count);
for (std::size_t i = 0; i < count; ++i)
for (auto const i : std::views::iota(0uz, count))
Comment thread
mathbunnyru marked this conversation as resolved.
Outdated
pool.push_back(seq.obj(start + i));
return pool;
}
Expand All @@ -158,7 +154,7 @@
Sequence seq(2);
std::vector<uint256> keys;
keys.reserve(count);
for (std::size_t i = 0; i < count; ++i)
for (auto const i : std::views::iota(0uz, count))
keys.push_back(seq.key(i));
return keys;
}
Expand Down Expand Up @@ -206,16 +202,16 @@
makeShuffle(std::size_t size, std::uint64_t seed)
{
std::vector<std::size_t> v(size);
std::iota(v.begin(), v.end(), std::size_t{0});
std::ranges::iota(v, 0uz);
beast::xor_shift_engine gen(seed);
std::shuffle(v.begin(), v.end(), gen);
std::ranges::shuffle(v, gen);
return v;
}

// Partition a pool into fixed-size batches. Any trailing remainder shorter than
// `batchSize` is dropped, so every returned batch has exactly `batchSize`.
inline std::vector<Batch>
sliceBatches(Batch const& pool, std::size_t batchSize)
slicePreciseBatches(Batch const& pool, std::size_t batchSize)

Check warning on line 214 in src/benchmarks/libxrpl/nodestore/NodeStoreBench.h

View check run for this annotation

Codecov / codecov/patch

src/benchmarks/libxrpl/nodestore/NodeStoreBench.h#L214

Added line #L214 was not covered by tests
Comment thread
godexsoft marked this conversation as resolved.
Outdated
{
std::vector<Batch> batches;
if (batchSize == 0)
Expand All @@ -228,13 +224,10 @@

/**
* @brief RAII owner of a NodeStore Backend opened on a private temporary directory.
*
* Member declaration order matters: `tempDir` is declared first so it is
* destroyed last, after the backend has closed and released its files.
*/
struct BackendHarness
{
beast::TempDir tempDir;
beast::TempDir tempDir; ///< Declared first so it is destroyed last
DummyScheduler scheduler;
beast::Journal journal{beast::Journal::getNullSink()};
std::unique_ptr<Backend> backend;
Expand Down
Loading
Loading