mdbx: переработка инициализации, проверки и импорта dbi-хендлов в транзакциях.

Ранее инициализация в транзакциях структур данных, связанных с
dbi-хендлами и subDb, выполнялась непосредственно при запуске
транзакций. Что в сценариях с большим кол-вом dbi-дексприторов (например
libfpta) порождало заметные накладные расходы, которые расли линейно от
общего кол-ва открытых subDb, а не от реально используемых в транзакции.
При использовании одной-двух сотен хендлов, при старте каждой транзакции
могли копироваться и/или обнуляться десятки килобайт. Теперь этот
недостаток устранен.

Изменена схема инициализации, валидации и импорта хендлов открытых после
старта транзакции:

1) Инициализация теперь выполняется отложенна, а при старте транзации
   обнуляется только массив с однобайтовыми статустами dbi-хендлов.
   При этом доступнва опция сборки `MDBX_ENABLE_DBI_SPARSE`, при активации
   которой используется битовая карты, что снижает объем инициализации
   при старте транзакции в 8 раз (CHAR_BIT).

2) Переработана валидация dbi-хендлов на входах API, с уменьшением кол-ва
   проверок и ветвлений до теоретического минимума.

3) Переработ импорт dbi-хендов открытых после старта транзакци, теперь
   при этом не захватывается мьютекс.
This commit is contained in:
Леонид Юрьев (Leonid Yuriev) 2023-11-05 22:10:29 +03:00
parent 796e56b9b9
commit e6af7d7c53
9 changed files with 1068 additions and 785 deletions

View File

@ -531,6 +531,7 @@ add_mdbx_option(MDBX_ENABLE_BIGFOOT "Chunking long list of retired pages during
add_mdbx_option(MDBX_ENABLE_PGOP_STAT "Gathering statistics for page operations" ON)
add_mdbx_option(MDBX_ENABLE_PROFGC "Profiling of GC search and updates" OFF)
mark_as_advanced(MDBX_ENABLE_PROFGC)
add_mdbx_option(MDBX_ENABLE_DBI_SPARSE "FIXME" ON)
if(NOT MDBX_AMALGAMATED_SOURCE)
if(CMAKE_CONFIGURATION_TYPES OR CMAKE_BUILD_TYPE_UPPERCASE STREQUAL "DEBUG")

8
mdbx.h
View File

@ -1921,7 +1921,7 @@ enum MDBX_error_t {
MDBX_TOO_LARGE = -30417,
/** A thread has attempted to use a not owned object,
* e.g. a transaction that started by another thread. */
* e.g. a transaction that started by another thread */
MDBX_THREAD_MISMATCH = -30416,
/** Overlapping read and write transactions for the current thread */
@ -1936,8 +1936,12 @@ enum MDBX_error_t {
/** Alternative/Duplicate LCK-file is exists and should be removed manually */
MDBX_DUPLICATED_CLK = -30413,
/** Some cursors and/or other resources should be closed before subDb or
* corresponding DBI-handle could be (re)used */
MDBX_DANGLING_DBI = -30412,
/* The last of MDBX-added error codes */
MDBX_LAST_ADDED_ERRCODE = MDBX_DUPLICATED_CLK,
MDBX_LAST_ADDED_ERRCODE = MDBX_DANGLING_DBI,
#if defined(_WIN32) || defined(_WIN64)
MDBX_ENODATA = ERROR_HANDLE_EOF,

View File

@ -559,6 +559,7 @@ MDBX_DECLARE_EXCEPTION(thread_mismatch);
MDBX_DECLARE_EXCEPTION(transaction_full);
MDBX_DECLARE_EXCEPTION(transaction_overlapping);
MDBX_DECLARE_EXCEPTION(duplicated_lck_file);
MDBX_DECLARE_EXCEPTION(dangling_map_id);
#undef MDBX_DECLARE_EXCEPTION
[[noreturn]] LIBMDBX_API void throw_too_small_target_buffer();

View File

@ -5,9 +5,9 @@ N | MASK | ENV | TXN | DB | PUT | DBI | NOD
2 |0000 0004|ALLOC_COLSC|TXN_DIRTY |DUPSORT | |DBI_FRESH |F_DUPDATA|P_OVERFLOW| |
3 |0000 0008|ALLOC_SSCAN|TXN_SPILLS |INTEGERKEY| |DBI_CREAT | |P_META | |
4 |0000 0010|ALLOC_FIFO |TXN_HAS_CHILD |DUPFIXED |NOOVERWRITE|DBI_VALID | |P_BAD | |
5 |0000 0020| |TXN_DRAINED_GC|INTEGERDUP|NODUPDATA |DBI_USRVALID| |P_LEAF2 | |
6 |0000 0040| | |REVERSEDUP|CURRENT |DBI_DUPDATA | |P_SUBP | |
7 |0000 0080| | | |ALLDUPS |DBI_AUDITED | | | |
5 |0000 0020| |TXN_DRAINED_GC|INTEGERDUP|NODUPDATA | | |P_LEAF2 | |
6 |0000 0040| | |REVERSEDUP|CURRENT |DBI_OLDEN | |P_SUBP | |
7 |0000 0080| | | |ALLDUPS |DBI_LINDO | | | |
8 |0000 0100| _MAY_MOVE | | | | | | | <= |
9 |0000 0200| _MAY_UNMAP| | | | | | | <= |
10|0000 0400| | | | | | | | |

View File

@ -33,6 +33,7 @@
#cmakedefine01 MDBX_ENABLE_BIGFOOT
#cmakedefine01 MDBX_ENABLE_PGOP_STAT
#cmakedefine01 MDBX_ENABLE_PROFGC
#cmakedefine01 MDBX_ENABLE_DBI_SPARSE
/* Windows */
#cmakedefine01 MDBX_WITHOUT_MSVC_CRT

1803
src/core.c

File diff suppressed because it is too large Load Diff

View File

@ -1192,19 +1192,23 @@ struct MDBX_txn {
/* Array of MDBX_db records for each known DB */
MDBX_db *mt_dbs;
#if MDBX_ENABLE_DBI_SPARSE
unsigned *mt_dbi_sparse;
#endif /* MDBX_ENABLE_DBI_SPARSE */
/* Non-shared DBI state flags inside transaction */
#define DBI_DIRTY 0x01 /* DB was written in this txn */
#define DBI_STALE 0x02 /* Named-DB record is older than txnID */
#define DBI_FRESH 0x04 /* Named-DB handle opened in this txn */
#define DBI_CREAT 0x08 /* Named-DB handle created in this txn */
#define DBI_VALID 0x10 /* Handle is valid, see also DB_VALID */
#define DBI_USRVALID 0x20 /* As DB_VALID, but not set for FREE_DBI */
#define DBI_AUDIT 0x40 /* Internal flag for accounting during audit */
#define DBI_DIRTY 0x01 /* DB was written in this txn */
#define DBI_STALE 0x02 /* Named-DB record is older than txnID */
#define DBI_FRESH 0x04 /* Named-DB handle opened in this txn */
#define DBI_CREAT 0x08 /* Named-DB handle created in this txn */
#define DBI_VALID 0x10 /* Handle is valid, see also DB_VALID */
#define DBI_OLDEN 0x40 /* Handle was closed/reopened outside txn */
#define DBI_LINDO 0x80 /* Lazy initialization done for DBI-slot */
/* Array of non-shared txn's flags of DBI */
uint8_t *mt_dbi_state;
/* Array of sequence numbers for each DB handle. */
MDBX_atomic_uint32_t *mt_dbi_seqs;
uint32_t *mt_dbi_seqs;
MDBX_cursor **mt_cursors;
MDBX_canary mt_canary;
@ -1660,7 +1664,8 @@ typedef struct MDBX_node {
/* mdbx_dbi_open() flags */
#define DB_USABLE_FLAGS (DB_PERSISTENT_FLAGS | MDBX_CREATE | MDBX_DB_ACCEDE)
#define DB_VALID 0x8000 /* DB handle is valid, for me_db_flags */
#define DB_VALID 0x8000u /* DB handle is valid, for me_db_flags */
#define DB_POISON 0x7fffu /* update pending */
#define DB_INTERNAL_FLAGS DB_VALID
#if DB_INTERNAL_FLAGS & DB_USABLE_FLAGS

View File

@ -286,6 +286,8 @@ DEFINE_EXCEPTION(thread_mismatch)
DEFINE_EXCEPTION(transaction_full)
DEFINE_EXCEPTION(transaction_overlapping)
DEFINE_EXCEPTION(duplicated_lck_file)
DEFINE_EXCEPTION(dangling_map_id)
#undef DEFINE_EXCEPTION
__cold const char *error::what() const noexcept {
@ -372,6 +374,7 @@ __cold void error::throw_exception() const {
CASE_EXCEPTION(transaction_full, MDBX_TXN_FULL);
CASE_EXCEPTION(transaction_overlapping, MDBX_TXN_OVERLAPPING);
CASE_EXCEPTION(duplicated_lck_file, MDBX_DUPLICATED_CLK);
CASE_EXCEPTION(dangling_map_id, MDBX_DANGLING_DBI);
#undef CASE_EXCEPTION
default:
if (is_mdbx_error())

View File

@ -163,6 +163,13 @@
#error MDBX_AVOID_MSYNC must be defined as 0 or 1
#endif /* MDBX_AVOID_MSYNC */
/** FIXME */
#ifndef MDBX_ENABLE_DBI_SPARSE
#define MDBX_ENABLE_DBI_SPARSE 1
#elif !(MDBX_ENABLE_DBI_SPARSE == 0 || MDBX_ENABLE_DBI_SPARSE == 1)
#error MDBX_ENABLE_DBI_SPARSE must be defined as 0 or 1
#endif /* MDBX_ENABLE_DBI_SPARSE */
/** Controls sort order of internal page number lists.
* This mostly experimental/advanced option with not for regular MDBX users.
* \warning The database format depend on this option and libmdbx built with