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