summaryrefslogtreecommitdiff
path: root/libs/libmdbx/src/test/ttl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'libs/libmdbx/src/test/ttl.cc')
-rw-r--r--libs/libmdbx/src/test/ttl.cc262
1 files changed, 0 insertions, 262 deletions
diff --git a/libs/libmdbx/src/test/ttl.cc b/libs/libmdbx/src/test/ttl.cc
deleted file mode 100644
index e3927d9cd4..0000000000
--- a/libs/libmdbx/src/test/ttl.cc
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * Copyright 2017-2020 Leonid Yuriev <leo@yuriev.ru>
- * and other libmdbx authors: please see AUTHORS file.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted only as authorized by the OpenLDAP
- * Public License.
- *
- * A copy of this license is available in the file LICENSE in the
- * top-level directory of the distribution or, alternatively, at
- * <http://www.OpenLDAP.org/license.html>.
- */
-
-#include "test.h"
-#include <cmath>
-#include <deque>
-
-/* LY: тест "эмуляцией time-to-live":
- * - организуется "скользящее окно", которое двигается вперед вдоль
- * числовой оси каждую транзакцию.
- * - по переднему краю "скользящего окна" записи добавляются в таблицу,
- * а по заднему удаляются.
- * - количество добавляемых/удаляемых записей псевдослучайно зависит
- * от номера транзакции, но с экспоненциальным распределением.
- * - размер "скользящего окна" также псевдослучайно зависит от номера
- * транзакции с "отрицательным" экспоненциальным распределением
- * MAX_WIDTH - exp(rnd(N)), при уменьшении окна сдвигается задний
- * край и удаляются записи позади него.
- *
- * Таким образом имитируется поведение таблицы с TTL: записи стохастически
- * добавляются и удаляются, но изредка происходит массивное удаление.
- */
-
-unsigned testcase_ttl::edge2count(uint64_t edge) {
- const double rnd = u64_to_double1(prng64_map1_white(edge));
- const unsigned count = std::lrint(std::pow(sliding.max_step_size, rnd));
- // average value: (X - 1) / ln(X), where X = sliding.max_step_size
- return count;
-}
-
-unsigned testcase_ttl::edge2window(uint64_t edge) {
- const double rnd = u64_to_double1(bleach64(edge));
- const unsigned size = sliding.max_window_size -
- std::lrint(std::pow(sliding.max_window_size, rnd));
- // average value: Y - (Y - 1) / ln(Y), where Y = sliding.max_window_size
- return size;
-}
-
-static inline double estimate(const double x, const double y) {
- /* среднее кол-во операций N = X' * Y', где X' и Y' средние значения
- * размера окна и кол-ва добавляемых за один шаг записей:
- * X' = (X - 1) / ln(X), где X = sliding.max_step_size
- * Y' = Y - (Y - 1) / ln(Y), где Y = sliding.max_window_size */
- return (x - 1) / std::log(x) * (y - (y - 1) / std::log(y));
-}
-
-bool testcase_ttl::setup() {
- const unsigned window_top_lower =
- 7 /* нижний предел для верхней границы диапазона, в котором будет
- стохастически колебаться размер окна */
- ;
- const unsigned count_top_lower =
- 7 /* нижний предел для верхней границы диапазона, в котором будет
- стохастически колебаться кол-во записей добавляемых на одном шаге */
- ;
-
- /* для параметризации используем подходящие параметры,
- * которые не имеют здесь смысла в первоначальном значении. */
- const double ratio =
- double(config.params.batch_read ? config.params.batch_read : 1) /
- double(config.params.batch_write ? config.params.batch_write : 1);
-
- /* проще найти двоичным поиском (вариация метода Ньютона) */
- double hi = config.params.test_nops, lo = 1;
- double x = std::sqrt(hi + lo) / ratio;
- while (hi > lo) {
- const double n = estimate(x, x * ratio);
- if (n > config.params.test_nops)
- hi = x - 1;
- else
- lo = x + 1;
- x = (hi + lo) / 2;
- }
-
- sliding.max_step_size = std::lrint(x);
- if (sliding.max_step_size < count_top_lower)
- sliding.max_step_size = count_top_lower;
- sliding.max_window_size = std::lrint(x * ratio);
- if (sliding.max_window_size < window_top_lower)
- sliding.max_window_size = window_top_lower;
-
- while (estimate(sliding.max_step_size, sliding.max_window_size) >
- config.params.test_nops * 2.0) {
- if (ratio * sliding.max_step_size > sliding.max_window_size) {
- if (sliding.max_step_size < count_top_lower)
- break;
- sliding.max_step_size = sliding.max_step_size * 7 / 8;
- } else {
- if (sliding.max_window_size < window_top_lower)
- break;
- sliding.max_window_size = sliding.max_window_size * 7 / 8;
- }
- }
-
- log_verbose("come up window_max %u from `batch_read`",
- sliding.max_window_size);
- log_verbose("come up step_max %u from `batch_write`", sliding.max_step_size);
- return inherited::setup();
-}
-
-bool testcase_ttl::run() {
- int err = db_open__begin__table_create_open_clean(dbi);
- if (unlikely(err != MDBX_SUCCESS)) {
- log_notice("ttl: bailout-prepare due '%s'", mdbx_strerror(err));
- return false;
- }
-
- uint64_t seed =
- prng64_map2_white(config.params.keygen.seed) + config.actor_id;
- keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */);
- key = keygen::alloc(config.params.keylen_max);
- data = keygen::alloc(config.params.datalen_max);
- const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT)
- ? MDBX_NODUPDATA
- : MDBX_NODUPDATA | MDBX_NOOVERWRITE;
-
- std::deque<std::pair<uint64_t, unsigned>> fifo;
- uint64_t serial = 0;
- bool rc = false;
- unsigned clear_wholetable_passed = 0;
- unsigned clear_stepbystep_passed = 0;
- unsigned dbfull_passed = 0;
- unsigned loops = 0;
- bool keyspace_overflow = false;
- while (true) {
- const uint64_t salt = prng64_white(seed) /* mdbx_txn_id(txn_guard.get()) */;
-
- const unsigned window_width =
- (!should_continue() || flipcoin_x4()) ? 0 : edge2window(salt);
- unsigned head_count = edge2count(salt);
- log_debug("ttl: step #%" PRIu64 " (serial %" PRIu64
- ", window %u, count %u) salt %" PRIu64,
- nops_completed, serial, window_width, head_count, salt);
-
- 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;
- log_trace("ttl: pop-tail (serial %" PRIu64 ", count %u)", tail_serial,
- tail_count);
- fifo.pop_back();
- for (unsigned n = 0; n < tail_count; ++n) {
- log_trace("ttl: remove-tail %" PRIu64, tail_serial);
- generate_pair(tail_serial);
- err = remove(key, data);
- if (unlikely(err != MDBX_SUCCESS)) {
- if (err == MDBX_MAP_FULL && config.params.ignore_dbfull) {
- log_notice("ttl: tail-bailout due '%s'", mdbx_strerror(err));
- goto bailout;
- }
- failure_perror("mdbx_del(tail)", err);
- }
- if (unlikely(!keyvalue_maker.increment(tail_serial, 1)))
- failure("ttl: unexpected key-space overflow on the tail");
- }
- report(tail_count);
- }
- } else {
- log_trace("ttl: purge state");
- db_table_clear(dbi);
- fifo.clear();
- clear_wholetable_passed += 1;
- report(1);
- }
-
- err = breakable_restart();
- if (unlikely(err != MDBX_SUCCESS)) {
- log_notice("ttl: bailout at commit due '%s'", mdbx_strerror(err));
- break;
- }
- if (!speculum_verify()) {
- log_notice("ttl: bailout after tail-trim");
- 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("ttl: skip head-grow to avoid one more dbfull (was %u, "
- "underutilization %.2f%%)",
- dbfull_passed, underutilization_x256 / 2.560);
- continue;
- }
- fifo.push_front(std::make_pair(serial, head_count));
- retry:
- for (unsigned n = 0; n < head_count; ++n) {
- log_trace("ttl: insert-head %" PRIu64, serial);
- generate_pair(serial);
- err = insert(key, data, insert_flags);
- if (unlikely(err != MDBX_SUCCESS)) {
- if ((err == MDBX_TXN_FULL || err == MDBX_MAP_FULL) &&
- config.params.ignore_dbfull) {
- log_notice("ttl: head-insert skip due '%s'", mdbx_strerror(err));
- txn_restart(true, false);
- serial = fifo.front().first;
- fifo.front().second = head_count = n;
- dbfull_passed += 1;
- goto retry;
- }
- failure_perror("mdbx_put(head)", err);
- }
-
- if (unlikely(!keyvalue_maker.increment(serial, 1))) {
- log_notice("ttl: unexpected key-space overflow");
- keyspace_overflow = true;
- txn_restart(true, false);
- serial = fifo.front().first;
- fifo.front().second = head_count = n;
- goto retry;
- }
- }
- err = breakable_restart();
- if (unlikely(err != MDBX_SUCCESS)) {
- log_notice("ttl: head-commit skip due '%s'", mdbx_strerror(err));
- serial = fifo.front().first;
- fifo.pop_front();
- }
- if (!speculum_verify()) {
- log_notice("ttl: bailout after head-grow");
- return false;
- }
- loops += 1;
- } else if (fifo.empty()) {
- log_notice("ttl: done %u whole loops, %" PRIu64 " ops, %" PRIu64 " items",
- loops, nops_completed, serial);
- rc = true;
- break;
- } else {
- log_notice("ttl: done, wait for empty, skip head-grow");
- }
- }
-
-bailout:
- txn_end(true);
- if (dbi) {
- if (config.params.drop_table && !mode_readonly()) {
- txn_begin(false);
- db_table_drop(dbi);
- err = breakable_commit();
- if (unlikely(err != MDBX_SUCCESS)) {
- log_notice("ttl: bailout-clean due '%s'", mdbx_strerror(err));
- return false;
- }
- } else
- db_table_close(dbi);
- }
- return rc;
-}