Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 = sliceFixedBatches(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 i = 0uz; i < count; ++i)
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 i = 0uz; i < count; ++i)
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)
sliceFixedBatches(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
{
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