diff options
Diffstat (limited to 'libs/libmdbx/src/test/nested.cc')
-rw-r--r-- | libs/libmdbx/src/test/nested.cc | 130 |
1 files changed, 64 insertions, 66 deletions
diff --git a/libs/libmdbx/src/test/nested.cc b/libs/libmdbx/src/test/nested.cc index beebd88071..85df6fa62b 100644 --- a/libs/libmdbx/src/test/nested.cc +++ b/libs/libmdbx/src/test/nested.cc @@ -15,6 +15,25 @@ #include "test.h" #include <cmath> +/* LY: тест "эмуляцией time-to-live" с вложенными транзакциями: + * - организуется "скользящее окно", которое каждую транзакцию сдвигается + * вперед вдоль числовой оси. + * - по переднему краю "скользящего окна" записи добавляются в таблицу, + * а по заднему удаляются. + * - количество добавляемых/удаляемых записей псевдослучайно зависит + * от номера транзакции, но с экспоненциальным распределением. + * - размер "скользящего окна" также псевдослучайно зависит от номера + * транзакции с "отрицательным" экспоненциальным распределением + * MAX_WIDTH - exp(rnd(N)), при уменьшении окна сдвигается задний + * край и удаляются записи позади него. + * - групповое добавление данных в начало окна и групповое удаление в конце, + * преимущественно выполняются во вложенных транзакциях. + * - меньшая часть запускаемых вложенных транзакций отменяется, с последующим + * продолжением итераций с состояния предыдущиего коммита. + * + * Таким образом имитируется поведение таблицы с TTL: записи стохастически + * добавляются и удаляются, и изредка происходят массивные удаления. */ + bool testcase_nested::setup() { if (!inherited::setup()) return false; @@ -56,18 +75,6 @@ bool testcase_nested::teardown() { return inherited::teardown() && ok; } -static unsigned edge2window(uint64_t edge, unsigned window_max) { - const double rnd = u64_to_double1(bleach64(edge)); - const unsigned window = window_max - std::lrint(std::pow(window_max, rnd)); - return window; -} - -static unsigned edge2count(uint64_t edge, unsigned count_max) { - const double rnd = u64_to_double1(prng64_map1_white(edge)); - const unsigned count = std::lrint(std::pow(count_max, rnd)); - return count; -} - void testcase_nested::push_txn() { MDBX_txn *txn; unsigned flags = @@ -75,11 +82,7 @@ void testcase_nested::push_txn() { int err = mdbx_txn_begin(db_guard.get(), txn_guard.get(), flags, &txn); if (unlikely(err != MDBX_SUCCESS)) failure_perror("mdbx_txn_begin(nested)", err); -#if __cplusplus >= 201703L - stack.emplace(txn, serial, fifo, speculum); -#else - stack.push(std::make_tuple(scoped_txn_guard(txn), serial, fifo, speculum)); -#endif + stack.emplace(scoped_txn_guard(txn), serial, fifo, speculum); std::swap(txn_guard, std::get<0>(stack.top())); log_verbose("begin level#%zu txn #%" PRIu64 ", flags 0x%x, serial %" PRIu64, stack.size(), mdbx_txn_id(txn), flags, serial); @@ -150,7 +153,8 @@ bool testcase_nested::stochastic_breakable_restart_with_nested( } bool testcase_nested::trim_tail(unsigned window_width) { - if (window_width) { + if (window_width || flipcoin()) { + clear_stepbystep_passed += window_width == 0; while (fifo.size() > window_width) { uint64_t tail_serial = fifo.back().first; const unsigned tail_count = fifo.back().second; @@ -171,6 +175,7 @@ bool testcase_nested::trim_tail(unsigned window_width) { if (unlikely(!keyvalue_maker.increment(tail_serial, 1))) failure("nested: unexpected key-space overflow on the tail"); } + report(tail_count); } } else if (!fifo.empty()) { log_verbose("nested: purge state %" PRIu64 " - %" PRIu64 ", fifo-items %zu", @@ -178,7 +183,8 @@ bool testcase_nested::trim_tail(unsigned window_width) { fifo.size()); db_table_clear(dbi, txn_guard.get()); fifo.clear(); - speculum.clear(); + clear_wholetable_passed += 1; + report(1); } return true; } @@ -198,6 +204,7 @@ retry: log_notice("nested: head-insert skip due '%s'", mdbx_strerror(err)); head_count = n; stochastic_breakable_restart_with_nested(true); + dbfull_passed += 1; goto retry; } failure_perror("mdbx_put(head)", err); @@ -205,7 +212,10 @@ retry: if (unlikely(!keyvalue_maker.increment(serial, 1))) { log_notice("nested: unexpected key-space overflow"); - return false; + keyspace_overflow = true; + head_count = n; + stochastic_breakable_restart_with_nested(true); + goto retry; } } @@ -213,48 +223,19 @@ retry: } bool testcase_nested::run() { - /* LY: тест "эмуляцией time-to-live" с вложенными транзакциями: - * - организуется "скользящее окно", которое каждую транзакцию сдвигается - * вперед вдоль числовой оси. - * - по переднему краю "скользящего окна" записи добавляются в таблицу, - * а по заднему удаляются. - * - количество добавляемых/удаляемых записей псевдослучайно зависит - * от номера транзакции, но с экспоненциальным распределением. - * - размер "скользящего окна" также псевдослучайно зависит от номера - * транзакции с "отрицательным" экспоненциальным распределением - * MAX_WIDTH - exp(rnd(N)), при уменьшении окна сдвигается задний - * край и удаляются записи позади него. - * - групповое добавление данных в начало окна и групповое уделение в конце, - * в половине случаев выполняются во вложенных транзакциях. - * - половина запускаемых вложенных транзакций отменяется, последуюим - * повтором групповой операции. - * - * Таким образом имитируется поведение таблицы с TTL: записи стохастически - * добавляются и удаляются, но изредка происходят массивные удаления. */ - - /* LY: для параметризации используем подходящие параметры, которые не имеют - * здесь смысла в первоначальном значении. */ - const unsigned window_max_lower = 333; - const unsigned count_max_lower = 333; - - const unsigned window_max = (config.params.batch_read > window_max_lower) - ? config.params.batch_read - : window_max_lower; - const unsigned count_max = (config.params.batch_write > count_max_lower) - ? config.params.batch_write - : count_max_lower; - log_verbose("nested: using `batch_read` value %u for window_max", window_max); - log_verbose("nested: using `batch_write` value %u for count_max", count_max); - uint64_t seed = prng64_map2_white(config.params.keygen.seed) + config.actor_id; - while (should_continue()) { + clear_wholetable_passed = 0; + clear_stepbystep_passed = 0; + dbfull_passed = 0; + unsigned loops = 0; + while (true) { const uint64_t salt = prng64_white(seed) /* mdbx_txn_id(txn_guard.get()) */; const unsigned window_width = - flipcoin_x4() ? 0 : edge2window(salt, window_max); - const unsigned head_count = edge2count(salt, count_max); - log_debug("nested: step #%zu (serial %" PRIu64 + (!should_continue() || flipcoin_x4()) ? 0 : edge2window(salt); + const unsigned head_count = edge2count(salt); + log_debug("nested: step #%" PRIu64 " (serial %" PRIu64 ", window %u, count %u) salt %" PRIu64, nops_completed, serial, window_width, head_count, salt); @@ -269,16 +250,33 @@ bool testcase_nested::run() { return false; } - if (!grow_head(head_count)) - return false; - if (!stochastic_breakable_restart_with_nested()) - log_notice("nested: skip commit/restart after head-grow"); - if (!speculum_verify()) { - log_notice("nested: bailout after head-grow"); - return false; + if (!keyspace_overflow && (should_continue() || !clear_wholetable_passed || + !clear_stepbystep_passed)) { + unsigned underutilization_x256 = + txn_underutilization_x256(txn_guard.get()); + if (dbfull_passed > underutilization_x256) { + log_notice("nested: skip head-grow to avoid one more dbfull (was %u, " + "underutilization %.2f%%)", + dbfull_passed, underutilization_x256 / 2.560); + continue; + } + if (!grow_head(head_count)) + return false; + if (!stochastic_breakable_restart_with_nested()) + log_notice("nested: skip commit/restart after head-grow"); + if (!speculum_verify()) { + log_notice("nested: bailout after head-grow"); + return false; + } + loops += 1; + } else if (fifo.empty()) { + log_notice("nested: done %u whole loops, %" PRIu64 " ops, %" PRIu64 + " items", + loops, nops_completed, serial); + break; + } else { + log_notice("nested: done, wait for empty, skip head-grow"); } - - report(1); } while (!stack.empty()) |