20 #include <test/nodestore/TestBase.h>
21 #include <ripple/nodestore/DummyScheduler.h>
22 #include <ripple/nodestore/Manager.h>
23 #include <ripple/basics/BasicConfig.h>
24 #include <ripple/basics/safe_cast.h>
25 #include <ripple/unity/rocksdb.h>
26 #include <ripple/beast/utility/temp_dir.h>
27 #include <ripple/beast/xor_shift_engine.h>
28 #include <ripple/beast/unit_test.h>
29 #include <test/unit_test/SuiteJournal.h>
30 #include <beast/unit_test/thread.hpp>
31 #include <boost/algorithm/string.hpp>
44 #ifndef NODESTORE_TIMING_DO_VERIFY
45 #define NODESTORE_TIMING_DO_VERIFY 0
52 template <
class Generator>
57 using result_type =
typename Generator::result_type;
58 while (bytes >=
sizeof(result_type))
61 memcpy(buffer, &v,
sizeof(v));
62 buffer =
reinterpret_cast<std::uint8_t*
>(buffer) +
sizeof(v);
69 memcpy(buffer, &v, bytes);
126 std::move(value),
key);
172 for (
auto iter = config.begin(); iter != config.end(); ++iter)
173 s += (iter != config.begin() ?
"," :
"") +
174 iter->first +
"=" + iter->second;
184 (d.
count() / 1000.) <<
"s";
195 boost::algorithm::is_any_of (
","));
204 template <
class Body>
219 template <
class... Args>
240 template <
class Body,
class... Args>
243 std::size_t number_of_threads, Args
const&... args)
248 for (
std::size_t id = 0;
id < number_of_threads; ++id)
256 template <
class Body,
class... Args>
259 std::size_t number_of_threads, Args
const&... args)
264 for (
std::size_t id = 0;
id < number_of_threads; ++id)
280 auto backend =
make_Backend (config, scheduler, journal);
281 BEAST_EXPECT(backend !=
nullptr);
293 Body (suite& s,
Backend& backend)
309 suite_.fail(e.
what());
316 parallel_for<Body>(params.
items,
321 #if NODESTORE_TIMING_DO_VERIFY
335 auto backend =
make_Backend (config, scheduler, journal);
336 BEAST_EXPECT(backend !=
nullptr);
355 , dist_ (0, params.
items - 1)
366 obj = seq1_.
obj(dist_(gen_));
367 backend_.
fetch(obj->getHash().data(), &result);
368 suite_.expect(result &&
isSame(result, obj));
372 suite_.fail(e.
what());
383 #if NODESTORE_TIMING_DO_VERIFY
397 auto backend =
make_Backend (config, scheduler, journal);
398 BEAST_EXPECT(backend !=
nullptr);
419 , dist_ (0, params.
items - 1)
428 auto const key = seq2_.
key(i);
430 backend_.
fetch(key.data(), &result);
431 suite_.expect(! result);
435 suite_.fail(e.
what());
447 #if NODESTORE_TIMING_DO_VERIFY
461 auto backend =
make_Backend (config, scheduler, journal);
462 BEAST_EXPECT(backend !=
nullptr);
487 , dist_ (0, params.
items - 1)
498 auto const key = seq2_.
key(dist_(gen_));
500 backend_.
fetch(key.data(), &result);
501 suite_.expect(! result);
507 obj = seq1_.
obj(dist_(gen_));
508 backend_.
fetch(obj->getHash().data(), &result);
509 suite_.expect(result &&
isSame(result, obj));
514 suite_.fail(e.
what());
526 #if NODESTORE_TIMING_DO_VERIFY
544 auto backend =
make_Backend (config, scheduler, journal);
545 BEAST_EXPECT(backend !=
nullptr);
546 backend->setDeletePath();
570 , recent_ (params.
items, params.
items * 2 - 1)
571 , older_ (0, params.
items - 1)
580 if (rand_(gen_) < 200)
585 auto const j = older_(gen_);
588 backend_.
fetch(obj->getHash().data(), &result);
589 suite_.expect(result !=
nullptr);
590 suite_.expect(
isSame(result, obj));
594 p[0] = rand_(gen_) < 50 ? 0 : 1;
596 for (
int q = 0; q < 2; ++q)
605 auto const j = recent_(gen_);
607 backend_.
fetch(obj->getHash().data(), &result);
608 suite_.expect(! result ||
616 auto const j = i + params_.
items;
625 suite_.fail(e.
what());
637 #if NODESTORE_TIMING_DO_VERIFY
656 (this->*f)(config, params, journal);
657 return std::chrono::duration_cast<duration_type> (
667 for (
auto const& test : tests)
668 if (w < test.first.size())
669 w = test.first.size();
671 threads <<
" Thread" << (threads > 1 ?
"s" :
"") <<
", " <<
676 for (
auto const& test : tests)
677 ss <<
" " << setw(w) << test.first;
684 for (
auto const& config_string : config_strings)
693 config.
set (
"path", tempDir.
path());
697 for (
auto const& test : tests)
699 do_test (test.second, config, params, journal));
709 testcase (
"Timing", beast::unit_test::abort_on_fail);
719 #if RIPPLE_ROCKSDB_AVAILABLE
720 ";type=rocksdb,open_files=2000,filter_bits=12,cache_mb=256,"
721 "file_size_mb=8,file_size_mult=2"
724 ";type=memory|path=NodeStore"
737 auto args = arg().empty() ? default_args : arg();
739 boost::split (config_strings, args,
740 boost::algorithm::is_any_of (
";"));
741 for (
auto iter = config_strings.
begin();
742 iter != config_strings.
end();)
744 iter = config_strings.
erase (iter);
748 do_tests ( 1, tests, config_strings);
749 do_tests ( 4, tests, config_strings);
750 do_tests ( 8, tests, config_strings);
static std::string to_string(Section const &config)
Simple NodeStore Scheduler that just peforms the tasks synchronously.
void batch(std::size_t n, Batch &b, std::size_t size)
Holds a collection of configuration values.
T setprecision(T... args)
std::uniform_int_distribution< std::uint32_t > d_size_
const std::size_t default_repeat
void do_insert(Section const &config, Params const ¶ms, beast::Journal journal)
Produces a sequence of secp256k1 key pairs.
static std::shared_ptr< NodeObject > createObject(NodeObjectType type, Blob &&data, uint256 const &hash)
Create an object from fields.
std::discrete_distribution< std::uint32_t > d_type_
void operator()(Args &&... args)
A namespace for easy access to logging severity values.
std::atomic< std::size_t > & c_
virtual void store(std::shared_ptr< NodeObject > const &object)=0
Store a single object.
void do_fetch(Section const &config, Params const ¶ms, beast::Journal journal)
void(Timing_test::*)(Section const &, Params const &, beast::Journal) test_func
constexpr static std::size_t size()
void append(std::vector< std::string > const &lines)
Append a set of lines to this section.
static void rngcpy(void *buffer, std::size_t bytes, Generator &g)
void do_tests(std::size_t threads, test_list const &tests, std::vector< std::string > const &config_strings)
void parallel_for(std::size_t const n, std::size_t number_of_threads, Args const &... args)
BEAST_DEFINE_TESTSUITE_MANUAL_PRIO(Timing, NodeStore, ripple, 1)
void do_mixed(Section const &config, Params const ¶ms, beast::Journal journal)
std::shared_ptr< NodeObject > obj(std::size_t n)
void Rethrow()
Rethrow the exception currently being handled.
void do_work(Section const &config, Params const ¶ms, beast::Journal journal)
void seed(result_type seed)
A generic endpoint for log messages.
void do_missing(Section const &config, Params const ¶ms, beast::Journal journal)
Sequence(std::uint8_t prefix)
std::string path() const
Get the native path for the temporary directory.
uint256 key(std::size_t n)
T emplace_back(T... args)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
void set(std::string const &key, std::string const &value)
Set a key/value pair.
std::unique_ptr< Backend > make_Backend(Section const &config, Scheduler &scheduler, beast::Journal journal)
Create a Backend.
static Section parse(std::string s)
bool isSame(std::shared_ptr< NodeObject > const &lhs, std::shared_ptr< NodeObject > const &rhs)
Returns true if objects are identical.
static std::string to_string(duration_type const &d)
parallel_for_lambda(std::size_t n, std::atomic< std::size_t > &c)
beast::xor_shift_engine gen_
const std::size_t default_items
duration_type do_test(test_func f, Section const &config, Params const ¶ms, beast::Journal journal)
virtual Status fetch(void const *key, std::shared_ptr< NodeObject > *pObject)=0
Fetch a single object.
RAII temporary directory.
T & get(EitherAmount &amt)
void parallel_for_id(std::size_t const n, std::size_t number_of_threads, Args const &... args)
A backend used for the NodeStore.