Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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 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)
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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the benefit of this renaming? If renaming is necessary, wouldn't sliceFixedBatches be more appropriate?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because that was suggested by @mathbunnyru : #7317 (comment)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sliceFixedBatches is a great name, let's use that

{
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