2020-02-07 00:46:59 +08:00
<!-- Required extensions: pymdownx.betterem, pymdownx.tilde, pymdownx.emoji, pymdownx.tasklist, pymdownx.superfences -->
2020-09-07 21:15:22 +08:00
> Please refer to the online [documentation](https://erthink.github.io/libmdbx/)
> with [`C` API description](https://erthink.github.io/libmdbx/group__c__api.html)
2020-09-25 07:27:40 +08:00
> and pay attention to the preliminary [`C++` API](https://github.com/erthink/libmdbx/blob/devel/mdbx.h%2B%2B).
2020-11-18 17:37:27 +08:00
>
2020-09-22 11:51:47 +08:00
> Questions, feedback and suggestions are welcome to the [Telegram' group](https://t.me/libmdbx).
2020-11-18 17:37:27 +08:00
>
> For NEWS take a look to the [ChangeLog](./ChangeLog.md).
libmdbx
========
2020-09-07 21:15:22 +08:00
2020-07-21 06:24:29 +08:00
<!-- section - begin overview -->
2020-01-10 00:10:35 +08:00
_libmdbx_ is an extremely fast, compact, powerful, embedded,
2020-07-21 06:24:29 +08:00
transactional [key-value database ](https://en.wikipedia.org/wiki/Key-value_database ),
with [permissive license ](./LICENSE ).
2020-09-30 01:14:08 +08:00
_libmdbx_ has a specific set of properties and capabilities,
2020-07-21 06:24:29 +08:00
focused on creating unique lightweight solutions.
2020-01-05 05:34:44 +08:00
2020-07-05 05:33:33 +08:00
1. Allows **a swarm of multi-threaded processes to
2020-02-25 20:01:25 +08:00
[ACID ]((https://en.wikipedia.org/wiki/ACID ))ly read and update** several
key-value [maps ](https://en.wikipedia.org/wiki/Associative_array ) and
2020-07-05 05:33:33 +08:00
[multimaps ](https://en.wikipedia.org/wiki/Multimap ) in a locally-shared
2020-02-25 20:01:25 +08:00
database.
2020-01-05 05:34:44 +08:00
2020-02-25 20:01:25 +08:00
2. Provides **extraordinary performance** , minimal overhead through
[Memory-Mapping ](https://en.wikipedia.org/wiki/Memory-mapped_file ) and
`Olog(N)` operations costs by virtue of [B+
tree](https://en.wikipedia.org/wiki/B%2B_tree).
2020-01-05 05:34:44 +08:00
2020-07-05 05:33:33 +08:00
3. Requires **no maintenance and no crash recovery** since it doesn't use
2020-02-25 20:01:25 +08:00
[WAL ](https://en.wikipedia.org/wiki/Write-ahead_logging ), but that might
be a caveat for write-intensive workloads with durability requirements.
2020-01-05 05:34:44 +08:00
2020-09-30 01:14:08 +08:00
4. **Compact and friendly for fully embedding** . Only ≈25KLOC of `C11` ,
≈64K x86 binary code of core, no internal threads neither server process(es),
but implements a simplified variant of the [Berkeley
2020-02-25 20:01:25 +08:00
DB](https://en.wikipedia.org/wiki/Berkeley_DB) and
2020-01-05 05:34:44 +08:00
[dbm ](https://en.wikipedia.org/wiki/DBM_(computing )) API.
5. Enforces [serializability ](https://en.wikipedia.org/wiki/Serializability ) for
writers just by single
[mutex ](https://en.wikipedia.org/wiki/Mutual_exclusion ) and affords
[wait-free ](https://en.wikipedia.org/wiki/Non-blocking_algorithm#Wait-freedom )
for parallel readers without atomic/interlocked operations, while
**writing and reading transactions do not block each other**.
6. **Guarantee data integrity** after crash unless this was explicitly
neglected in favour of write performance.
2020-04-14 19:56:18 +08:00
7. Supports Linux, Windows, MacOS, Android, iOS, FreeBSD, DragonFly, Solaris,
2020-01-05 05:34:44 +08:00
OpenSolaris, OpenIndiana, NetBSD, OpenBSD and other systems compliant with
**POSIX.1-2008**.
2020-07-21 06:24:29 +08:00
<!-- section - end -->
2020-01-05 05:34:44 +08:00
2020-09-30 01:14:08 +08:00
Historically, _libmdbx_ is a deeply revised and extended descendant of the amazing
2020-01-05 05:34:44 +08:00
[Lightning Memory-Mapped Database ](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database ).
2020-09-30 01:14:08 +08:00
_libmdbx_ inherits all benefits from _LMDB_ , but resolves some issues and adds [a set of improvements ](#improvements-beyond-lmdb ).
2020-01-05 05:34:44 +08:00
2020-07-21 06:24:29 +08:00
<!-- section - begin mithril -->
2020-01-05 05:34:44 +08:00
The next version is under active non-public development from scratch and will be
2020-07-21 06:24:29 +08:00
released as _**MithrilDB**_ and `libmithrildb` for libraries & packages.
2019-08-29 23:30:25 +08:00
Admittedly mythical [Mithril ](https://en.wikipedia.org/wiki/Mithril ) is
resembling silver but being stronger and lighter than steel. Therefore
2020-07-05 05:33:33 +08:00
_MithrilDB_ is a rightly relevant name.
2020-01-05 05:34:44 +08:00
> _MithrilDB_ will be radically different from _libmdbx_ by the new
> database format and API based on C++17, as well as the [Apache 2.0
> License](https://www.apache.org/licenses/LICENSE-2.0). The goal of this
> revolution is to provide a clearer and robust API, add more features and
2020-07-05 05:33:33 +08:00
> new valuable properties of the database.
2020-07-21 06:24:29 +08:00
<!-- section - end -->
2019-08-20 20:04:56 +08:00
2020-02-29 05:57:22 +08:00
[![https://t.me/libmdbx ](https://raw.githubusercontent.com/wiki/erthink/libmdbx/img/telegram.png )](https://t.me/libmdbx)
2021-01-29 23:37:04 +08:00
[![GithubCI ](https://github.com/erthink/libmdbx/workflows/CI/badge.svg )](https://github.com/erthink/libmdbx/actions?query=workflow%3ACI)
[![AppveyorCI ](https://ci.appveyor.com/api/projects/status/ue94mlopn50dqiqg/branch/master?svg=true )](https://ci.appveyor.com/project/leo-yuriev/libmdbx/branch/master)
2020-05-04 23:55:53 +08:00
[![CircleCI ](https://circleci.com/gh/erthink/libmdbx/tree/master.svg?style=svg )](https://circleci.com/gh/erthink/libmdbx/tree/master)
2021-01-29 23:37:04 +08:00
[![CirrusCI ](https://api.cirrus-ci.com/github/erthink/libmdbx.svg )](https://cirrus-ci.com/github/erthink/libmdbx)
2019-08-21 06:05:57 +08:00
[![Coverity Scan Status ](https://scan.coverity.com/projects/12915/badge.svg )](https://scan.coverity.com/projects/reopen-libmdbx)
2017-11-15 23:47:39 +08:00
2020-01-05 05:34:44 +08:00
*The Future will (be) [Positive ](https://www.ptsecurity.com ). Всё будет хорошо.*
-----
2019-08-21 06:05:57 +08:00
## Table of Contents
2020-07-21 06:24:29 +08:00
- [Characteristics ](#characteristics )
2020-01-05 05:34:44 +08:00
- [Features ](#features )
- [Limitations ](#limitations )
2020-07-21 06:24:29 +08:00
- [Gotchas ](#gotchas )
2019-08-21 06:05:57 +08:00
- [Comparison with other databases ](#comparison-with-other-databases )
2020-01-05 05:34:44 +08:00
- [Improvements beyond LMDB ](#improvements-beyond-lmdb )
2019-08-21 06:05:57 +08:00
- [History & Acknowledgments ](#history )
- [Usage ](#usage )
2021-07-21 07:28:44 +08:00
- [Building and Testing ](#building-and-testing )
2020-01-05 05:34:44 +08:00
- [API description ](#api-description )
2019-08-21 06:05:57 +08:00
- [Bindings ](#bindings )
2018-01-18 20:47:17 +08:00
- [Performance comparison ](#performance-comparison )
2019-08-21 06:05:57 +08:00
- [Integral performance ](#integral-performance )
- [Read scalability ](#read-scalability )
- [Sync-write mode ](#sync-write-mode )
- [Lazy-write mode ](#lazy-write-mode )
- [Async-write mode ](#async-write-mode )
- [Cost comparison ](#cost-comparison )
2017-02-08 22:52:05 +08:00
2020-07-21 06:24:29 +08:00
# Characteristics
<!-- section - begin characteristics -->
2017-07-21 06:59:05 +08:00
2020-01-05 05:34:44 +08:00
## Features
2017-07-21 06:59:05 +08:00
2020-01-05 05:34:44 +08:00
- Key-value data model, keys are always sorted.
2019-09-30 07:40:19 +08:00
2020-01-05 05:34:44 +08:00
- Fully [ACID ](https://en.wikipedia.org/wiki/ACID )-compliant, through to
[MVCC ](https://en.wikipedia.org/wiki/Multiversion_concurrency_control )
and [CoW ](https://en.wikipedia.org/wiki/Copy-on-write ).
2019-09-30 07:40:19 +08:00
2020-01-05 05:34:44 +08:00
- Multiple key-value sub-databases within a single datafile.
2017-02-08 22:52:05 +08:00
2020-01-05 05:34:44 +08:00
- Range lookups, including range query estimation.
2018-07-30 07:55:13 +08:00
2020-01-05 05:34:44 +08:00
- Efficient support for short fixed length keys, including native 32/64-bit integers.
2017-11-15 23:47:39 +08:00
2020-01-05 05:34:44 +08:00
- Ultra-efficient support for [multimaps ](https://en.wikipedia.org/wiki/Multimap ). Multi-values sorted, searchable and iterable. Keys stored without duplication.
2019-09-30 07:40:19 +08:00
2020-01-05 05:34:44 +08:00
- Data is [memory-mapped ](https://en.wikipedia.org/wiki/Memory-mapped_file ) and accessible directly/zero-copy. Traversal of database records is extremely-fast.
2019-09-30 07:40:19 +08:00
2020-01-05 05:34:44 +08:00
- Transactions for readers and writers, ones do not block others.
2017-02-08 22:52:05 +08:00
2020-07-05 05:33:33 +08:00
- Writes are strongly serialized. No transaction conflicts nor deadlocks.
2018-07-30 07:55:13 +08:00
2020-01-05 05:34:44 +08:00
- Readers are [non-blocking ](https://en.wikipedia.org/wiki/Non-blocking_algorithm ), notwithstanding [snapshot isolation ](https://en.wikipedia.org/wiki/Snapshot_isolation ).
2017-01-18 21:40:56 +08:00
2020-01-05 05:34:44 +08:00
- Nested write transactions.
2017-09-17 20:07:32 +08:00
2020-07-05 05:33:33 +08:00
- Reads scale linearly across CPUs.
2017-09-17 20:07:32 +08:00
2020-01-05 05:34:44 +08:00
- Continuous zero-overhead database compactification.
2019-08-21 06:05:57 +08:00
2020-01-05 05:34:44 +08:00
- Automatic on-the-fly database size adjustment.
2017-09-17 20:07:32 +08:00
2020-01-05 05:34:44 +08:00
- Customizable database page size.
2017-01-18 21:40:56 +08:00
2020-01-05 05:34:44 +08:00
- `Olog(N)` cost of lookup, insert, update, and delete operations by virtue of [B+ tree characteristics ](https://en.wikipedia.org/wiki/B%2B_tree#Characteristics ).
2018-07-30 07:55:13 +08:00
2020-01-05 05:34:44 +08:00
- Online hot backup.
2018-07-30 07:55:13 +08:00
2020-01-05 05:34:44 +08:00
- Append operation for efficient bulk insertion of pre-sorted data.
- No [WAL ](https://en.wikipedia.org/wiki/Write-ahead_logging ) nor any
transaction journal. No crash recovery needed. No maintenance is required.
- No internal cache and/or memory management, all done by basic OS services.
2018-07-30 07:55:13 +08:00
2020-01-05 05:34:44 +08:00
## Limitations
2018-07-30 07:55:13 +08:00
2021-03-19 23:31:15 +08:00
- **Page size**: a power of 2, minimum `256` (mostly for testing), maximum `65536` bytes, default `4096` bytes.
2021-05-10 04:29:55 +08:00
- **Key size**: minimum `0` , maximum ≈½ pagesize (`2022` bytes for default 4K pagesize, `32742` bytes for 64K pagesize).
- **Value size**: minimum `0` , maximum `2146435072` (`0x7FF00000`) bytes for maps, ≈½ pagesize for multimaps (`2022` bytes for default 4K pagesize, `32742` bytes for 64K pagesize).
2021-03-19 23:31:15 +08:00
- **Write transaction size**: up to `1327217884` pages (`4.944272` TiB for default 4K pagesize, `79.108351` TiB for 64K pagesize).
- **Database size**: up to `2147483648` pages (≈`8.0` TiB for default 4K pagesize, ≈`128.0` TiB for 64K pagesize).
2020-01-05 05:34:44 +08:00
- **Maximum sub-databases**: `32765` .
2018-07-30 07:55:13 +08:00
2020-07-21 06:24:29 +08:00
## Gotchas
2018-07-30 07:55:13 +08:00
2020-01-05 05:34:44 +08:00
1. There cannot be more than one writer at a time, i.e. no more than one write transaction at a time.
2018-07-30 07:55:13 +08:00
2020-09-30 01:14:08 +08:00
2. _libmdbx_ is based on [B+ tree ](https://en.wikipedia.org/wiki/B%2B_tree ), so access to database pages is mostly random.
2020-01-05 05:34:44 +08:00
Thus SSDs provide a significant performance boost over spinning disks for large databases.
2017-01-18 21:40:56 +08:00
2021-07-20 21:27:41 +08:00
3. _libmdbx_ uses [shadow paging ](https://en.wikipedia.org/wiki/Shadow_paging ) instead of [WAL ](https://en.wikipedia.org/wiki/Write-ahead_logging ).
Thus syncing data to disk might be a bottleneck for write intensive workload.
2017-07-04 17:07:05 +08:00
2021-07-20 21:27:41 +08:00
4. _libmdbx_ uses [copy-on-write ](https://en.wikipedia.org/wiki/Copy-on-write ) for [snapshot isolation ](https://en.wikipedia.org/wiki/Snapshot_isolation ) during updates,
but read transactions prevents recycling an old retired/freed pages, since it read ones. Thus altering of data during a parallel
2020-01-05 05:34:44 +08:00
long-lived read operation will increase the process work set, may exhaust entire free database space,
the database can grow quickly, and result in performance degradation.
Try to avoid long running read transactions.
2020-09-30 01:14:08 +08:00
5. _libmdbx_ is extraordinarily fast and provides minimal overhead for data access,
2020-07-05 05:33:33 +08:00
so you should reconsider using brute force techniques and double check your code.
2020-09-30 01:14:08 +08:00
On the one hand, in the case of _libmdbx_ , a simple linear search may be more profitable than complex indexes.
2020-07-05 05:33:33 +08:00
On the other hand, if you make something suboptimally, you can notice detrimentally only on sufficiently large data.
2020-01-05 05:34:44 +08:00
2020-07-21 06:24:29 +08:00
## Comparison with other databases
2020-01-05 05:34:44 +08:00
For now please refer to [chapter of "BoltDB comparison with other
databases"](https://github.com/coreos/bbolt#comparison-with-other-databases)
which is also (mostly) applicable to _libmdbx_ .
2017-07-04 17:07:05 +08:00
2020-07-21 06:24:29 +08:00
<!-- section - end -->
<!-- section - begin improvements -->
2020-01-05 05:34:44 +08:00
Improvements beyond LMDB
========================
2017-11-15 23:47:39 +08:00
2019-12-08 02:50:19 +08:00
_libmdbx_ is superior to legendary _[LMDB](https://symas.com/lmdb/)_ in
2019-09-30 07:40:19 +08:00
terms of features and reliability, not inferior in performance. In
2019-12-08 02:50:19 +08:00
comparison to _LMDB_ , _libmdbx_ make things "just work" perfectly and
2019-09-30 07:40:19 +08:00
out-of-the-box, not silently and catastrophically break down. The list
below is pruned down to the improvements most notable and obvious from
the user's point of view.
2020-07-21 06:24:29 +08:00
## Added Features
2020-01-05 05:34:44 +08:00
1. Keys could be more than 2 times longer than _LMDB_ .
2021-05-10 04:29:55 +08:00
> For DB with default page size _libmdbx_ support keys up to 2022 bytes
> and up to 32742 bytes for 64K page size. _LMDB_ allows key size up to
2019-12-08 02:50:19 +08:00
> 511 bytes and may silently loses data with large values.
2021-02-07 08:14:49 +08:00
2. Up to 30% faster than _LMDB_ in [CRUD ](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete ) benchmarks.
2019-12-08 02:50:19 +08:00
> Benchmarks of the in-[tmpfs](https://en.wikipedia.org/wiki/Tmpfs) scenarios,
2021-02-07 08:14:49 +08:00
> that tests the speed of the engine itself, showned that _libmdbx_ 10-20% faster than _LMDB_,
> and up to 30% faster when _libmdbx_ compiled with specific build options
> which downgrades several runtime checks to be match with LMDB behaviour.
>
2020-07-05 05:33:33 +08:00
> These and other results could be easily reproduced with [ioArena](https://github.com/pmwkaa/ioarena) just by `make bench-quartet` command,
2019-12-08 02:50:19 +08:00
> including comparisons with [RockDB](https://en.wikipedia.org/wiki/RocksDB)
> and [WiredTiger](https://en.wikipedia.org/wiki/WiredTiger).
2020-01-05 05:34:44 +08:00
3. Automatic on-the-fly database size adjustment, both increment and reduction.
2020-07-05 05:33:33 +08:00
> _libmdbx_ manages the database size according to parameters specified
2019-09-30 07:40:19 +08:00
> by `mdbx_env_set_geometry()` function,
> ones include the growth step and the truncation threshold.
2020-03-18 21:52:07 +08:00
>
> Unfortunately, on-the-fly database size adjustment doesn't work under [Wine](https://en.wikipedia.org/wiki/Wine_(software))
> due to its internal limitations and unimplemented functions, i.e. the `MDBX_UNABLE_EXTEND_MAPSIZE` error will be returned.
2019-09-30 07:40:19 +08:00
2019-12-08 02:50:19 +08:00
4. Automatic continuous zero-overhead database compactification.
2021-04-25 18:54:28 +08:00
> During each commit _libmdbx_ merges a freeing pages which adjacent with the unallocated area
2020-07-05 05:33:33 +08:00
> at the end of file, and then truncates unused space when a lot enough of.
2020-01-05 05:34:44 +08:00
5. The same database format for 32- and 64-bit builds.
> _libmdbx_ database format depends only on the [endianness](https://en.wikipedia.org/wiki/Endianness) but not on the [bitness](https://en.wiktionary.org/wiki/bitness).
6. LIFO policy for Garbage Collection recycling. This can significantly increase write performance due write-back disk cache up to several times in a best case scenario.
2020-09-22 11:51:47 +08:00
> LIFO means that for reuse will be taken the latest becomes unused pages.
2019-09-30 07:40:19 +08:00
> Therefore the loop of database pages circulation becomes as short as possible.
2020-01-05 05:34:44 +08:00
> In other words, the set of pages, that are (over)written in memory and on disk during a series of write transactions, will be as small as possible.
> Thus creates ideal conditions for the battery-backed or flash-backed disk cache efficiency.
2019-09-30 07:40:19 +08:00
2020-01-05 05:34:44 +08:00
7. Fast estimation of range query result volume, i.e. how many items can
2020-07-05 05:33:33 +08:00
be found between a `KEY1` and a `KEY2` . This is a prerequisite for build
2019-09-30 07:40:19 +08:00
and/or optimize query execution plans.
2020-08-02 00:13:17 +08:00
> _libmdbx_ performs a rough estimate based on common B-tree pages of the paths from root to corresponding keys.
2019-09-30 07:40:19 +08:00
2020-09-25 07:27:40 +08:00
8. `mdbx_chk` utility for database integrity check.
Since version 0.9.1, the utility supports checking the database using any of the three meta pages and the ability to switch to it.
2019-09-30 07:40:19 +08:00
2021-02-07 08:14:49 +08:00
9. Support for opening databases in the exclusive mode, including on a network share.
2019-03-06 05:40:53 +08:00
2021-02-07 08:14:49 +08:00
10. Zero-length for keys and values.
2017-07-04 17:07:05 +08:00
2021-02-07 08:14:49 +08:00
11. Ability to determine whether the particular data is on a dirty page
2020-01-05 05:34:44 +08:00
or not, that allows to avoid copy-out before updates.
2017-01-09 06:19:24 +08:00
2021-02-07 08:14:49 +08:00
12. Extended information of whole-database, sub-databases, transactions, readers enumeration.
2020-01-05 05:34:44 +08:00
> _libmdbx_ provides a lot of information, including dirty and leftover pages
> for a write transaction, reading lag and holdover space for read transactions.
2017-01-09 06:19:24 +08:00
2021-02-07 08:14:49 +08:00
13. Extended update and delete operations.
2020-07-05 05:33:33 +08:00
> _libmdbx_ allows one _at once_ with getting previous value
2020-01-05 05:34:44 +08:00
> and addressing the particular item from multi-value with the same key.
2018-01-18 03:19:59 +08:00
2021-02-07 08:14:49 +08:00
14. Useful runtime options for tuning engine to application's requirements and use cases specific.
15. Automated steady sync-to-disk upon several thresholds and/or timeout via cheap polling.
16. Sequence generation and three persistent 64-bit markers.
17. Handle-Slow-Readers callback to resolve a database full/overflow issues due to long-lived read transaction(s).
18. Ability to determine whether the cursor is pointed to a key-value
pair, to the first, to the last, or not set to anything.
2020-07-21 06:24:29 +08:00
## Other fixes and specifics
2018-01-18 03:19:59 +08:00
2020-08-02 00:13:17 +08:00
1. Fixed more than 10 significant errors, in particular: page leaks,
wrong sub-database statistics, segfault in several conditions,
nonoptimal page merge strategy, updating an existing record with
a change in data size (including for multimap), etc.
2018-01-18 03:19:59 +08:00
2020-08-02 00:13:17 +08:00
2. All cursors can be reused and should be closed explicitly,
regardless ones were opened within a write or read transaction.
2018-01-18 03:19:59 +08:00
2020-01-05 05:34:44 +08:00
3. Opening database handles are spared from race conditions and
pre-opening is not needed.
2018-01-18 03:19:59 +08:00
2020-01-05 05:34:44 +08:00
4. Returning `MDBX_EMULTIVAL` error in case of ambiguous update or delete.
2017-07-04 17:07:05 +08:00
2020-01-05 05:34:44 +08:00
5. Guarantee of database integrity even in asynchronous unordered write-to-disk mode.
2020-08-02 00:13:17 +08:00
> _libmdbx_ propose additional trade-off by `MDBX_SAFE_NOSYNC` with append-like manner for updates,
> that avoids database corruption after a system crash contrary to LMDB.
> Nevertheless, the `MDBX_UTTERLY_NOSYNC` mode is available to match behaviour of the `MDB_NOSYNC` in LMDB.
2017-11-15 23:47:39 +08:00
2020-04-30 06:46:04 +08:00
6. On **MacOS & iOS** the `fcntl(F_FULLFSYNC)` syscall is used _by
2019-08-20 20:04:56 +08:00
default_ to synchronize data with the disk, as this is [the only way to
guarantee data
durability](https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fsync.2.html)
in case of power failure. Unfortunately, in scenarios with high write
2020-07-05 05:33:33 +08:00
intensity, the use of `F_FULLFSYNC` significantly degrades performance
2019-08-20 20:04:56 +08:00
compared to LMDB, where the `fsync()` syscall is used. Therefore,
_libmdbx_ allows you to override this behavior by defining the
`MDBX_OSX_SPEED_INSTEADOF_DURABILITY=1` option while build the library.
2020-01-05 05:34:44 +08:00
7. On **Windows** the `LockFileEx()` syscall is used for locking, since
2019-08-20 20:04:56 +08:00
it allows place the database on network drives, and provides protection
against incompetent user actions (aka
[poka-yoke ](https://en.wikipedia.org/wiki/Poka-yoke )). Therefore
2020-07-05 05:33:33 +08:00
_libmdbx_ may be a little lag in performance tests from LMDB where the
2019-08-20 20:04:56 +08:00
named mutexes are used.
2020-07-21 06:24:29 +08:00
<!-- section - end -->
<!-- section - begin history -->
# History
2020-09-30 01:14:08 +08:00
Historically, _libmdbx_ is a deeply revised and extended descendant of the
2020-07-21 06:24:29 +08:00
[Lightning Memory-Mapped Database ](https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database ).
2020-01-05 05:34:44 +08:00
At first the development was carried out within the
2020-02-18 07:22:47 +08:00
[ReOpenLDAP ](https://github.com/erthink/ReOpenLDAP ) project. About a
2020-07-05 05:33:33 +08:00
year later _libmdbx_ was separated into a standalone project, which was
2020-01-05 05:34:44 +08:00
[presented at Highload++ 2015
conference](http://www.highload.ru/2015/abstracts/1831.html).
2020-02-18 07:22:47 +08:00
Since 2017 _libmdbx_ is used in [Fast Positive Tables ](https://github.com/erthink/libfpta ),
2020-01-05 05:34:44 +08:00
and development is funded by [Positive Technologies ](https://www.ptsecurity.com ).
2017-07-04 17:07:05 +08:00
2020-07-21 06:24:29 +08:00
## Acknowledgments
2020-01-05 05:34:44 +08:00
Howard Chu < hyc @ openldap . org > is the author of LMDB, from which
2020-09-30 01:14:08 +08:00
originated the _libmdbx_ in 2015.
2020-01-05 05:34:44 +08:00
Martin Hedenfalk < martin @ bzero . se > is the author of `btree.c` code, which
2020-07-05 05:33:33 +08:00
was used to begin development of LMDB.
2019-07-16 08:16:25 +08:00
2020-07-21 06:24:29 +08:00
<!-- section - end -->
2019-09-30 07:40:19 +08:00
--------------------------------------------------------------------------------
2019-07-16 08:16:25 +08:00
2019-09-30 07:40:19 +08:00
Usage
=====
2019-07-16 08:16:25 +08:00
2020-07-21 06:24:29 +08:00
<!-- section - begin usage -->
Currently, libmdbx is only available in a
[source code ](https://en.wikipedia.org/wiki/Source_code ) form.
Packages support for common Linux distributions is planned in the future,
since release the version 1.0.
2021-05-13 17:19:18 +08:00
## Never use tarballs nor zips automatically provided by Github !
Please don't use tarballs nor zips which are automatically provided by Github.
These archives do not contain version information and thus are unfit to build _libmdbx_ .
Instead of ones just clone the git repository, either download a tarball or zip with the properly amalgamated source core.
Moreover, please vote for [ability of disabling auto-creation such unsuitable archives ](https://github.community/t/disable-tarball ).
2019-09-30 07:40:19 +08:00
## Source code embedding
2019-07-16 08:16:25 +08:00
2019-09-30 07:40:19 +08:00
_libmdbx_ provides two official ways for integration in source code form:
2019-07-16 08:16:25 +08:00
2019-09-30 07:40:19 +08:00
1. Using the amalgamated source code.
2020-07-05 05:33:33 +08:00
> The amalgamated source code includes all files required to build and
2019-09-30 07:40:19 +08:00
> use _libmdbx_, but not for testing _libmdbx_ itself.
2019-07-16 08:16:25 +08:00
2019-09-30 07:40:19 +08:00
2. Adding the complete original source code as a `git submodule` .
> This allows you to build as _libmdbx_ and testing tool.
> On the other hand, this way requires you to pull git tags, and use C++11 compiler for test tool.
2018-01-18 03:19:59 +08:00
2020-07-21 06:24:29 +08:00
_**Please, avoid using any other techniques.**_ Otherwise, at least
2019-09-30 07:40:19 +08:00
don't ask for support and don't name such chimeras `libmdbx` .
2019-08-21 06:05:57 +08:00
2020-07-05 05:33:33 +08:00
The amalgamated source code could be created from the original clone of git
2019-09-30 07:40:19 +08:00
repository on Linux by executing `make dist` . As a result, the desired
set of files will be formed in the `dist` subdirectory.
2019-08-21 06:05:57 +08:00
2021-07-21 07:28:44 +08:00
## Building and Testing
2019-08-21 06:05:57 +08:00
2019-09-30 07:40:19 +08:00
Both amalgamated and original source code provides build through the use
[CMake ](https://cmake.org/ ) or [GNU
Make](https://www.gnu.org/software/make/) with
[bash ](https://en.wikipedia.org/wiki/Bash_(Unix_shell )). All build ways
are completely traditional and have minimal prerequirements like
`build-essential` , i.e. the non-obsolete C/C++ compiler and a
[SDK ](https://en.wikipedia.org/wiki/Software_development_kit ) for the
target platform. Obviously you need building tools itself, i.e. `git` ,
2021-05-01 06:02:28 +08:00
`cmake` or GNU `make` with `bash` . For your convenience, `make help`
and `make options` are also available for listing existing targets
and build options respectively.
2019-08-21 06:05:57 +08:00
2021-08-01 22:58:42 +08:00
The only significant specificity is that git' tags are required
to build from complete (not amalgamated) source codes.
Executing ** `git fetch --tags --force --prune` ** is enough to get ones,
or `git fetch --unshallow --tags --prune --force` after the Github's
[`actions/checkout@v2` ](https://github.com/actions/checkout ) either set ** `fetch-depth: 0` ** for it.
2020-07-05 05:33:33 +08:00
So just using CMake or GNU Make in your habitual manner and feel free to
2019-09-30 07:40:19 +08:00
fill an issue or make pull request in the case something will be
unexpected or broken down.
2019-08-21 06:05:57 +08:00
2021-07-21 07:28:44 +08:00
### Testing
The amalgamated source code does not contain any tests for or several reasons.
Please read [the explanation ](https://github.com/erthink/libmdbx/issues/214#issuecomment-870717981 ) and don't ask to alter this.
So for testing _libmdbx_ itself you need a full source code, i.e. the clone of a git repository, there is no option.
The full source code of _libmdbx_ has a [`test` subdirectory ](https://github.com/erthink/libmdbx/tree/master/test ) with minimalistic test "framework".
Actually yonder is a source code of the `mdbx_test` – console utility which has a set of command-line options that allow construct and run a reasonable enough test scenarios.
This test utility is intended for _libmdbx_ 's developers for testing library itself, but not for use by users.
Therefore, only basic information is provided:
- There are few CRUD-based test cases (hill, TTL, nested, append, jitter, etc),
which can be combined to test the concurrent operations within shared database in a multi-processes environment.
This is the `basic` test scenario.
- The `Makefile` provide several self-described targets for testing: `smoke` , `test` , `check` , `memcheck` , `test-valgrind` ,
`test-asan` , `test-leak` , `test-ubsan` , `cross-gcc` , `cross-qemu` , `gcc-analyzer` , `smoke-fault` , `smoke-singleprocess` ,
`test-singleprocess` , 'long-test'. Please run `make --help` if doubt.
- In addition to the `mdbx_test` utility, there is the script [`long_stochastic.sh` ](https://github.com/erthink/libmdbx/blob/master/test/long_stochastic.sh ),
which calls `mdbx_test` by going through set of modes and options, with gradually increasing the number of operations and the size of transactions.
This script is used for mostly of all automatic testing, including `Makefile` targets and Continuous Integration.
- Brief information of available command-line options is available by `--help` .
However, you should dive into source code to get all, there is no option.
Anyway, no matter how thoroughly the _libmdbx_ is tested, you should rely only on your own tests for a few reasons:
1. Mostly of all use cases are unique.
So it is no warranty that your use case was properly tested, even the _libmdbx_ 's tests engages stochastic approach.
2. If there are problems, then your test on the one hand will help to verify whether you are using _libmdbx_ correctly,
on the other hand it will allow to reproduce the problem and insure against regression in a future.
3. Actually you should rely on than you checked by yourself or take a risk.
2021-06-02 22:08:40 +08:00
### Common important details
#### Build reproducibility
By default _libmdbx_ track build time via `MDBX_BUILD_TIMESTAMP` build option and macro.
2021-07-20 21:27:41 +08:00
So for a [reproducible builds ](https://en.wikipedia.org/wiki/Reproducible_builds ) you should predefine/override it to known fixed string value.
For instance:
2021-06-02 22:08:40 +08:00
- for reproducible build with make: `make MDBX_BUILD_TIMESTAMP=unknown ` ...
- or during configure by CMake: `cmake -DMDBX_BUILD_TIMESTAMP:STRING=unknown ` ...
Of course, in addition to this, your toolchain must ensure the reproducibility of builds.
For more information please refer to [reproducible-builds.org ](https://reproducible-builds.org/ ).
2021-07-20 21:27:41 +08:00
#### Containers
There are no special traits nor quirks if you use libmdbx ONLY inside the single container.
But in a cross-container cases or with a host-container(s) mix the two major things MUST be
guaranteed:
1. Coherence of memory mapping content and unified page cache inside OS kernel for host and all container(s) operated with a some DB.
Basically this means must be only a single physical copy of each memory mapped DB' page in the system memory.
2. Uniqueness of PID values and/or a common space for ones:
- for POSIX systems: PID uniqueness for all processes operated with a DB.
I.e. the `--pid=host` is required for run DB-aware processes inside Docker,
either without host interaction a `--pid=container:<name|id>` with the same name/id.
- for non-POSIX (i.e. Windows) systems: inter-visibility of processes handles.
I.e. the `OpenProcess(SYNCHRONIZE, ..., PID)` must return reasonable error,
including `ERROR_ACCESS_DENIED` ,
but not the `ERROR_INVALID_PARAMETER` as for an invalid/non-existent PID.
2019-08-21 06:05:57 +08:00
#### DSO/DLL unloading and destructors of Thread-Local-Storage objects
When building _libmdbx_ as a shared library or use static _libmdbx_ as a
part of another dynamic library, it is advisable to make sure that your
system ensures the correctness of the call destructors of
2019-09-30 07:40:19 +08:00
Thread-Local-Storage objects when unloading dynamic libraries.
2019-08-21 06:05:57 +08:00
If this is not the case, then unloading a dynamic-link library with
_libmdbx_ code inside, can result in either a resource leak or a crash
due to calling destructors from an already unloaded DSO/DLL object. The
problem can only manifest in a multithreaded application, which makes
the unloading of shared dynamic libraries with _libmdbx_ code inside,
after using _libmdbx_ . It is known that TLS-destructors are properly
maintained in the following cases:
- On all modern versions of Windows (Windows 7 and later).
- On systems with the
[`__cxa_thread_atexit_impl()` ](https://sourceware.org/glibc/wiki/Destructor%20support%20for%20thread_local%20variables )
function in the standard C library, including systems with GNU libc
version 2.18 and later.
- On systems with libpthread/ntpl from GNU libc with bug fixes
[#21031 ](https://sourceware.org/bugzilla/show_bug.cgi?id=21031 ) and
[#21032 ](https://sourceware.org/bugzilla/show_bug.cgi?id=21032 ), or
where there are no similar bugs in the pthreads implementation.
### Linux and other platforms with GNU Make
To build the library it is enough to execute `make all` in the directory
2020-07-05 05:33:33 +08:00
of source code, and `make check` to execute the basic tests.
2019-08-21 06:05:57 +08:00
If the `make` installed on the system is not GNU Make, there will be a
lot of errors from make when trying to build. In this case, perhaps you
should use `gmake` instead of `make` , or even `gnu-make` , etc.
### FreeBSD and related platforms
As a rule, in such systems, the default is to use Berkeley Make. And GNU
Make is called by the gmake command or may be missing. In addition,
[bash ](https://en.wikipedia.org/wiki/Bash_(Unix_shell )) may be absent.
You need to install the required components: GNU Make, bash, C and C++
compilers compatible with GCC or CLANG. After that, to build the
2020-07-05 05:33:33 +08:00
library, it is enough to execute `gmake all` (or `make all` ) in the
2019-08-21 06:05:57 +08:00
directory with source code, and `gmake check` (or `make check` ) to run
the basic tests.
### Windows
2019-09-30 07:40:19 +08:00
For build _libmdbx_ on Windows the _original_ CMake and [Microsoft Visual
2020-05-11 05:25:18 +08:00
Studio 2019](https://en.wikipedia.org/wiki/Microsoft_Visual_Studio) are
2020-07-05 05:33:33 +08:00
recommended. Otherwise do not forget to add `ntdll.lib` to linking.
2019-08-21 06:05:57 +08:00
Building by MinGW, MSYS or Cygwin is potentially possible. However,
these scripts are not tested and will probably require you to modify the
2021-04-30 07:01:22 +08:00
`CMakeLists.txt` or `Makefile` respectively.
2019-09-30 07:40:19 +08:00
It should be noted that in _libmdbx_ was efforts to resolve
2021-04-30 07:01:22 +08:00
runtime dependencies from CRT and other MSVC libraries.
2021-04-30 01:09:16 +08:00
For this is enough to define the `MDBX_WITHOUT_MSVC_CRT` during build.
2019-08-21 06:05:57 +08:00
An example of running a basic test script can be found in the
[CI-script ](appveyor.yml ) for [AppVeyor ](https://www.appveyor.com/ ). To
run the [long stochastic test scenario ](test/long_stochastic.sh ),
[bash ](https://en.wikipedia.org/wiki/Bash_(Unix_shell )) is required, and
2020-07-05 05:33:33 +08:00
such testing is recommended with placing the test data on the
2019-08-21 06:05:57 +08:00
[RAM-disk ](https://en.wikipedia.org/wiki/RAM_drive ).
2020-07-05 05:33:33 +08:00
### Windows Subsystem for Linux
_libmdbx_ could be used in [WSL2 ](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux#WSL_2 )
but NOT in [WSL1 ](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux#WSL_1 ) environment.
This is a consequence of the fundamental shortcomings of _WSL1_ and cannot be fixed.
To avoid data loss, _libmdbx_ returns the `ENOLCK` (37, "No record locks available")
error when opening the database in a _WSL1_ environment.
2019-09-30 07:40:19 +08:00
### MacOS
2019-08-21 06:05:57 +08:00
Current [native build tools ](https://en.wikipedia.org/wiki/Xcode ) for
2019-09-30 07:40:19 +08:00
MacOS include GNU Make, CLANG and an outdated version of bash.
2019-08-21 06:05:57 +08:00
Therefore, to build the library, it is enough to run `make all` in the
directory with source code, and run `make check` to execute the base
tests. If something goes wrong, it is recommended to install
[Homebrew ](https://brew.sh/ ) and try again.
To run the [long stochastic test scenario ](test/long_stochastic.sh ), you
will need to install the current (not outdated) version of
[bash ](https://en.wikipedia.org/wiki/Bash_(Unix_shell )). To do this, we
recommend that you install [Homebrew ](https://brew.sh/ ) and then execute
`brew install bash` .
2020-04-14 19:56:18 +08:00
### Android
We recommend using CMake to build _libmdbx_ for Android.
Please refer to the [official guide ](https://developer.android.com/studio/projects/add-native-code ).
2020-04-08 07:05:18 +08:00
### iOS
2020-04-14 19:56:18 +08:00
To build _libmdbx_ for iOS, we recommend using CMake with the
2021-06-02 22:08:40 +08:00
["toolchain file" ](https://cmake.org/cmake/help/latest/variable/CMAKE_TOOLCHAIN_FILE.html )
2020-04-08 07:05:18 +08:00
from the [ios-cmake ](https://github.com/leetal/ios-cmake ) project.
2020-07-21 06:24:29 +08:00
<!-- section - end -->
2020-01-05 05:34:44 +08:00
## API description
2020-07-24 00:24:21 +08:00
Please refer to the online [_libmdbx_ API reference ](https://erthink.github.io/libmdbx/ )
and/or see the [mdbx.h ](mdbx.h ) header.
2020-01-05 05:34:44 +08:00
2020-07-21 06:24:29 +08:00
<!-- section - begin bindings -->
Bindings
========
2019-08-21 06:05:57 +08:00
2021-03-15 08:36:51 +08:00
| Runtime | Repo | Author |
2020-07-21 06:24:29 +08:00
| ------- | ------ | ------ |
2021-08-02 14:05:50 +08:00
| Haskell | [libmdbx-hs ](https://hackage.haskell.org/package/libmdbx ) | [Francisco Vallarino ](https://github.com/fjvallarino ) |
2021-07-21 22:39:34 +08:00
| Python (draft) | [python-bindings ](https://github.com/erthink/libmdbx/commits/python-bindings ) branch | [Noel Kuntze ](https://github.com/Thermi )
| NodeJS | [lmdbx-store ](https://github.com/kriszyp/lmdbx-store ) | [Kris Zyp ](https://github.com/kriszyp/ )
| NodeJS | [node-mdbx ](https://www.npmjs.com/package/node-mdbx/ ) | [Сергей Федотов ](mailto:sergey.fedotov@corp.mail.ru ) |
2021-03-15 08:36:51 +08:00
| Ruby | [ruby-mdbx ](https://rubygems.org/gems/mdbx/ ) | [Mahlon E. Smith ](https://github.com/mahlonsmith ) |
2021-02-07 19:32:27 +08:00
| Go | [mdbx-go ](https://github.com/torquem-ch/mdbx-go ) | [Alex Sharov ](https://github.com/AskAlexSharov ) |
2020-11-17 06:33:37 +08:00
| [Nim ](https://en.wikipedia.org/wiki/Nim_(programming_language )) | [NimDBX ](https://github.com/snej/nimdbx ) | [Jens Alfke ](https://github.com/snej )
2021-09-28 01:39:19 +08:00
| Rust | [mdbx-rs ](https://github.com/vorot93/mdbx-rs ) | [Artem Vorotnikov ](https://github.com/vorot93 ) |
| Java (obsolete) | [mdbxjni ](https://github.com/castortech/mdbxjni ) | [Castor Technologies ](https://castortech.com/ ) |
| .NET (obsolete) | [mdbx.NET ](https://github.com/wangjia184/mdbx.NET ) | [Jerry Wang ](https://github.com/wangjia184 ) |
2020-07-21 06:24:29 +08:00
<!-- section - end -->
2019-08-21 06:05:57 +08:00
2018-07-30 07:55:13 +08:00
--------------------------------------------------------------------------------
2018-01-18 03:19:59 +08:00
2020-07-21 06:24:29 +08:00
<!-- section - begin performance -->
2018-07-30 07:55:13 +08:00
Performance comparison
======================
2018-01-18 03:19:59 +08:00
2019-12-08 02:50:19 +08:00
All benchmarks were done in 2015 by [IOArena ](https://github.com/pmwkaa/ioarena )
2018-07-30 07:55:13 +08:00
and multiple [scripts ](https://github.com/pmwkaa/ioarena/tree/HL%2B%2B2015 )
2020-01-10 00:10:35 +08:00
runs on Lenovo Carbon-2 laptop, i7-4600U 2.1 GHz (2 physical cores, 4 HyperThreading cores), 8 Gb RAM,
2018-07-30 07:55:13 +08:00
SSD SAMSUNG MZNTD512HAGL-000L1 (DXT23L0Q) 512 Gb.
2018-01-18 03:19:59 +08:00
2019-08-21 06:05:57 +08:00
## Integral performance
2018-01-18 03:19:59 +08:00
2018-07-30 07:55:13 +08:00
Here showed sum of performance metrics in 3 benchmarks:
2018-01-18 03:19:59 +08:00
2020-07-05 05:33:33 +08:00
- Read/Search on the machine with 4 logical CPUs in HyperThreading mode (i.e. actually 2 physical CPU cores);
2018-01-18 03:19:59 +08:00
2018-07-30 07:55:13 +08:00
- Transactions with [CRUD ](https://en.wikipedia.org/wiki/CRUD )
operations in sync-write mode (fdatasync is called after each
transaction);
2018-01-18 03:19:59 +08:00
2018-07-30 07:55:13 +08:00
- Transactions with [CRUD ](https://en.wikipedia.org/wiki/CRUD )
operations in lazy-write mode (moment to sync data to persistent storage
is decided by OS).
2018-01-18 03:19:59 +08:00
2018-07-30 07:55:13 +08:00
*Reasons why asynchronous mode isn't benchmarked here:*
2018-01-18 03:19:59 +08:00
2018-07-30 07:55:13 +08:00
1. It doesn't make sense as it has to be done with DB engines, oriented
for keeping data in memory e.g. [Tarantool ](https://tarantool.io/ ),
[Redis ](https://redis.io/ )), etc.
2018-01-18 03:19:59 +08:00
2018-07-30 07:55:13 +08:00
2. Performance gap is too high to compare in any meaningful way.
2018-01-18 03:19:59 +08:00
2020-02-18 07:22:47 +08:00
![Comparison #1: Integral Performance ](https://raw.githubusercontent.com/wiki/erthink/libmdbx/img/perf-slide-1.png )
2017-01-18 21:40:56 +08:00
2017-07-04 17:07:05 +08:00
--------------------------------------------------------------------------------
2017-01-18 21:40:56 +08:00
2019-08-21 06:05:57 +08:00
## Read Scalability
2017-01-09 02:48:00 +08:00
2018-07-30 07:55:13 +08:00
Summary performance with concurrent read/search queries in 1-2-4-8
2020-07-05 05:33:33 +08:00
threads on the machine with 4 logical CPUs in HyperThreading mode (i.e. actually 2 physical CPU cores).
2017-01-09 06:19:24 +08:00
2020-02-18 07:22:47 +08:00
![Comparison #2: Read Scalability ](https://raw.githubusercontent.com/wiki/erthink/libmdbx/img/perf-slide-2.png )
2017-01-09 06:19:24 +08:00
2018-07-30 07:55:13 +08:00
--------------------------------------------------------------------------------
2017-01-18 21:40:56 +08:00
2019-08-21 06:05:57 +08:00
## Sync-write mode
2017-01-18 21:40:56 +08:00
2018-07-30 07:55:13 +08:00
- Linear scale on left and dark rectangles mean arithmetic mean
transactions per second;
2017-01-18 21:40:56 +08:00
2018-07-30 07:55:13 +08:00
- Logarithmic scale on right is in seconds and yellow intervals mean
execution time of transactions. Each interval shows minimal and maximum
execution time, cross marks standard deviation.
2017-01-18 21:40:56 +08:00
2018-07-30 07:55:13 +08:00
**10,000 transactions in sync-write mode**. In case of a crash all data
2020-07-05 05:33:33 +08:00
is consistent and conforms to the last successful transaction. The
2018-07-30 07:55:13 +08:00
[fdatasync ](https://linux.die.net/man/2/fdatasync ) syscall is used after
each write transaction in this mode.
2017-01-18 21:40:56 +08:00
2018-07-30 07:55:13 +08:00
In the benchmark each transaction contains combined CRUD operations (2
2020-07-05 05:33:33 +08:00
inserts, 1 read, 1 update, 1 delete). Benchmark starts on an empty database
2018-07-30 07:55:13 +08:00
and after full run the database contains 10,000 small key-value records.
2017-01-18 21:40:56 +08:00
2020-02-18 07:22:47 +08:00
![Comparison #3: Sync-write mode ](https://raw.githubusercontent.com/wiki/erthink/libmdbx/img/perf-slide-3.png )
2017-01-09 02:48:00 +08:00
2018-07-30 07:55:13 +08:00
--------------------------------------------------------------------------------
2017-01-09 02:48:00 +08:00
2019-08-21 06:05:57 +08:00
## Lazy-write mode
2017-01-09 02:48:00 +08:00
2018-07-30 07:55:13 +08:00
- Linear scale on left and dark rectangles mean arithmetic mean of
thousands transactions per second;
2017-01-09 02:48:00 +08:00
2018-07-30 07:55:13 +08:00
- Logarithmic scale on right in seconds and yellow intervals mean
execution time of transactions. Each interval shows minimal and maximum
execution time, cross marks standard deviation.
2017-01-09 02:48:00 +08:00
2018-07-30 07:55:13 +08:00
**100,000 transactions in lazy-write mode**. In case of a crash all data
2020-07-05 05:33:33 +08:00
is consistent and conforms to the one of last successful transactions, but
2018-07-30 07:55:13 +08:00
transactions after it will be lost. Other DB engines use
[WAL ](https://en.wikipedia.org/wiki/Write-ahead_logging ) or transaction
2020-07-05 05:33:33 +08:00
journal for that, which in turn depends on order of operations in the
2018-07-30 07:55:13 +08:00
journaled filesystem. _libmdbx_ doesn't use WAL and hands I/O operations
to filesystem and OS kernel (mmap).
2017-01-09 02:48:00 +08:00
2018-07-30 07:55:13 +08:00
In the benchmark each transaction contains combined CRUD operations (2
2020-07-05 05:33:33 +08:00
inserts, 1 read, 1 update, 1 delete). Benchmark starts on an empty database
2018-07-30 07:55:13 +08:00
and after full run the database contains 100,000 small key-value
records.
2017-01-09 02:48:00 +08:00
2020-02-18 07:22:47 +08:00
![Comparison #4: Lazy-write mode ](https://raw.githubusercontent.com/wiki/erthink/libmdbx/img/perf-slide-4.png )
2017-01-09 02:48:00 +08:00
2018-07-30 07:55:13 +08:00
--------------------------------------------------------------------------------
2017-01-09 02:48:00 +08:00
2019-08-21 06:05:57 +08:00
## Async-write mode
2017-01-09 02:48:00 +08:00
2018-07-30 07:55:13 +08:00
- Linear scale on left and dark rectangles mean arithmetic mean of
thousands transactions per second;
2017-02-08 22:52:05 +08:00
2018-07-30 07:55:13 +08:00
- Logarithmic scale on right in seconds and yellow intervals mean
execution time of transactions. Each interval shows minimal and maximum
execution time, cross marks standard deviation.
2017-02-08 22:52:05 +08:00
2021-07-20 21:27:41 +08:00
**1,000,000 transactions in async-write mode**.
In case of a crash all data is consistent and conforms to the one of last successful transactions,
but lost transaction count is much higher than in
2018-07-30 07:55:13 +08:00
lazy-write mode. All DB engines in this mode do as little writes as
possible on persistent storage. _libmdbx_ uses
[msync(MS_ASYNC) ](https://linux.die.net/man/2/msync ) in this mode.
2017-02-08 22:52:05 +08:00
2018-07-30 07:55:13 +08:00
In the benchmark each transaction contains combined CRUD operations (2
2020-07-05 05:33:33 +08:00
inserts, 1 read, 1 update, 1 delete). Benchmark starts on an empty database
2018-07-30 07:55:13 +08:00
and after full run the database contains 10,000 small key-value records.
2017-02-08 22:52:05 +08:00
2020-02-18 07:22:47 +08:00
![Comparison #5: Async-write mode ](https://raw.githubusercontent.com/wiki/erthink/libmdbx/img/perf-slide-5.png )
2017-02-08 22:52:05 +08:00
2018-07-30 07:55:13 +08:00
--------------------------------------------------------------------------------
2017-02-08 22:52:05 +08:00
2019-08-21 06:05:57 +08:00
## Cost comparison
2017-02-08 22:52:05 +08:00
2018-07-30 07:55:13 +08:00
Summary of used resources during lazy-write mode benchmarks:
2017-02-18 03:02:07 +08:00
2020-01-05 05:34:44 +08:00
- Read and write IOPs;
2017-02-18 03:02:07 +08:00
2018-07-30 07:55:13 +08:00
- Sum of user CPU time and sys CPU time;
2017-07-04 17:07:05 +08:00
2018-07-30 07:55:13 +08:00
- Used space on persistent storage after the test and closed DB, but not
waiting for the end of all internal housekeeping operations (LSM
compactification, etc).
2017-07-04 17:07:05 +08:00
2018-07-30 07:55:13 +08:00
_ForestDB_ is excluded because benchmark showed it's resource
2020-01-05 05:34:44 +08:00
consumption for each resource (CPU, IOPs) much higher than other engines
2018-07-30 07:55:13 +08:00
which prevents to meaningfully compare it with them.
2017-07-04 17:07:05 +08:00
2018-07-30 07:55:13 +08:00
All benchmark data is gathered by
[getrusage() ](http://man7.org/linux/man-pages/man2/getrusage.2.html )
2020-07-05 05:33:33 +08:00
syscall and by scanning the data directory.
2017-07-27 23:16:19 +08:00
2020-02-18 07:22:47 +08:00
![Comparison #6: Cost comparison ](https://raw.githubusercontent.com/wiki/erthink/libmdbx/img/perf-slide-6.png )
2017-07-27 23:38:08 +08:00
2020-07-21 06:24:29 +08:00
<!-- section - end -->
2017-07-27 23:16:19 +08:00
--------------------------------------------------------------------------------
2020-02-18 06:42:58 +08:00
#### This is a mirror of the origin repository that was moved to [abf.io](https://abf.io/erthink/) because of discriminatory restrictions for Russian Crimea.