summaryrefslogtreecommitdiff
path: root/libs/libmdbx/src/test/nested.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libmdbx/src/test/nested.cc')
-rw-r--r--libs/libmdbx/src/test/nested.cc130
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())