xrpld
Loading...
Searching...
No Matches
Handler_test.cpp
1
2#include <test/jtx/TestHelpers.h>
3
4#include <xrpld/rpc/detail/Handler.h>
5
6#include <xrpl/beast/unit_test/suite.h>
7
8#include <algorithm>
9#include <array>
10#include <cassert>
11#include <chrono>
12#include <cmath>
13#include <cstddef>
14#include <iostream>
15#include <random>
16#include <tuple>
17#include <vector>
18// cspell: words stdev
19
20namespace xrpl::test {
21
22// NOTE: there should be no need for this function;
23// `std::cout << some_duration` should just work if built with a compliant
24// C++20 compiler. Sadly, we are not using one, as of today
25// TODO: remove this operator<< overload when we bump compiler version
28{
29 return (os << ns.count() << "ns");
30}
31
32// NOTE This is a rather naive effort at a microbenchmark. Ideally we want
33// Google Benchmark, or something similar. Also, this actually does not belong
34// to unit tests, as it makes little sense to run it in conditions very
35// dissimilar to how xrpld will normally work.
36// TODO as https://github.com/XRPLF/rippled/issues/4765
37
39{
40 auto
41 time(std::size_t n, auto f, auto prng) -> auto
42 {
43 using clock = std::chrono::steady_clock;
44 assert(n > 0);
45 double sum = 0;
46 double sumSquared = 0;
47 std::size_t j = 0;
48 while (j < n)
49 {
50 // Generate 100 inputs upfront, separated from the inner loop
51 std::array<decltype(prng()), 100> inputs = {};
52 for (auto& i : inputs)
53 {
54 i = prng();
55 }
56
57 // Take 100 samples, then sort and throw away 35 from each end,
58 // using only middle 30. This helps to reduce measurement noise.
59 std::array<long, 100> samples = {};
60 for (std::size_t k = 0; k < 100; ++k)
61 {
62 auto start = std::chrono::steady_clock::now();
63 f(inputs[k]);
64 samples[k] = (std::chrono::steady_clock::now() - start).count();
65 }
66
67 std::ranges::sort(samples);
68 for (std::size_t k = 35; k < 65; ++k)
69 {
70 j += 1;
71 sum += samples[k];
72 sumSquared += (samples[k] * samples[k]);
73 }
74 }
75
76 double const meanSquared = (sum * sum) / (j * j);
77 return std::make_tuple(
78 clock::duration{static_cast<long>(sum / j)},
79 clock::duration{static_cast<long>(std::sqrt((sumSquared / j) - meanSquared))},
80 j);
81 }
82
83 void
85 {
86 testcase("Handler lookup performance");
87
89 std::ranlux48 prng(dev());
90
92
94
95 std::size_t dummy = 0;
96 auto const [mean, stdev, n] = time(
97 1'000'000,
98 [&](std::size_t i) {
99 auto const d = RPC::getHandler(1, false, names[i]);
100 dummy = dummy + i + (int)d->role;
101 },
102 [&]() -> std::size_t { return distr(prng); });
103
104 std::cout << "mean=" << mean << " stdev=" << stdev << " N=" << n << '\n';
105
106 BEAST_EXPECT(dummy != 0);
107 }
108
109public:
110 void
111 run() override
112 {
114 }
115};
116
118
119} // namespace xrpl::test
A testsuite class.
Definition suite.h:50
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
void run() override
Runs the suite.
auto time(std::size_t n, auto f, auto prng) -> auto
T make_tuple(T... args)
std::set< char const * > getHandlerNames()
Return names of all methods.
Definition Handler.cpp:484
Handler const * getHandler(unsigned version, bool betaEnabled, std::string const &name)
Definition Handler.cpp:478
std::ostream & operator<<(std::ostream &os, PrettyAmount const &amount)
Definition amount.cpp:46
auto makeVector(Input const &input)
BEAST_DEFINE_TESTSUITE_MANUAL(AMMCalc, app, xrpl)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
static auto sum(TCollection const &col)
Definition BookStep.cpp:993
T size(T... args)
T sort(T... args)
T sqrt(T... args)