Remove LMDB
Performance of history writes was very poor even with the code rewritten to accommodate the environment concept (see db_abstraction branch)
This commit is contained in:
parent
ffb4d4f158
commit
c958b3af49
@ -12,7 +12,6 @@ python:
|
|||||||
# command to install dependencies
|
# command to install dependencies
|
||||||
install:
|
install:
|
||||||
- pip install aiohttp
|
- pip install aiohttp
|
||||||
- pip install lmdb
|
|
||||||
- pip install plyvel
|
- pip install plyvel
|
||||||
- pip install pyrocksdb
|
- pip install pyrocksdb
|
||||||
- pip install pytest-cov
|
- pip install pytest-cov
|
||||||
|
|||||||
@ -66,11 +66,9 @@ These environment variables are optional:
|
|||||||
* **DB_ENGINE**
|
* **DB_ENGINE**
|
||||||
|
|
||||||
Database engine for the UTXO and history database. The default is
|
Database engine for the UTXO and history database. The default is
|
||||||
`leveldb`. Supported alternatives are `rocksdb` and `lmdb`. You
|
`leveldb`. The other alternative is `rocksdb`. You will need to
|
||||||
will need to install the appropriate python package for your engine.
|
install the appropriate python package for your engine. The value
|
||||||
The value is not case sensitive. Note that the current way
|
is not case sensitive.
|
||||||
ElectrumX uses LMDB results in poor performance. I intend to improve
|
|
||||||
this.
|
|
||||||
|
|
||||||
* **REORG_LIMIT**
|
* **REORG_LIMIT**
|
||||||
|
|
||||||
|
|||||||
@ -44,7 +44,7 @@
|
|||||||
#COIN = Bitcoin # lib/coins.py
|
#COIN = Bitcoin # lib/coins.py
|
||||||
#NET = mainnet # lib/coins.py
|
#NET = mainnet # lib/coins.py
|
||||||
#DB_ENGINE = leveldb
|
#DB_ENGINE = leveldb
|
||||||
#leveldb, rocksdb, lmdb (You'll need to install appropriate python packages)
|
#leveldb, rocksdb (You'll need to install appropriate python packages)
|
||||||
|
|
||||||
#REORG_LIMIT = 200
|
#REORG_LIMIT = 200
|
||||||
#maximum number of blocks to be able to handle in a chain
|
#maximum number of blocks to be able to handle in a chain
|
||||||
|
|||||||
@ -5,10 +5,7 @@
|
|||||||
# See the file "LICENCE" for information about the copyright
|
# See the file "LICENCE" for information about the copyright
|
||||||
# and warranty status of this software.
|
# and warranty status of this software.
|
||||||
|
|
||||||
'''Backend database abstraction.
|
'''Backend database abstraction.'''
|
||||||
|
|
||||||
The abstraction needs to be improved to not heavily penalise LMDB.
|
|
||||||
'''
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from functools import partial
|
from functools import partial
|
||||||
@ -161,68 +158,3 @@ class RocksDB(Storage):
|
|||||||
|
|
||||||
def iterator(self, prefix=b'', reverse=False):
|
def iterator(self, prefix=b'', reverse=False):
|
||||||
return RocksDB.Iterator(self.db, prefix, reverse)
|
return RocksDB.Iterator(self.db, prefix, reverse)
|
||||||
|
|
||||||
|
|
||||||
class LMDB(Storage):
|
|
||||||
'''RocksDB database engine.'''
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def import_module(cls):
|
|
||||||
import lmdb
|
|
||||||
cls.module = lmdb
|
|
||||||
|
|
||||||
def open(self, name, create):
|
|
||||||
# I don't see anything equivalent to max_open_files for for_sync
|
|
||||||
self.env = LMDB.module.Environment('.', subdir=True, create=create,
|
|
||||||
max_dbs=32, map_size=5 * 10 ** 10)
|
|
||||||
self.db = self.env.open_db(create=create)
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
self.env.close()
|
|
||||||
|
|
||||||
def get(self, key):
|
|
||||||
with self.env.begin(db=self.db) as tx:
|
|
||||||
return tx.get(key)
|
|
||||||
|
|
||||||
def put(self, key, value):
|
|
||||||
with self.env.begin(db=self.db, write=True) as tx:
|
|
||||||
tx.put(key, value)
|
|
||||||
|
|
||||||
def write_batch(self):
|
|
||||||
return self.env.begin(db=self.db, write=True)
|
|
||||||
|
|
||||||
def iterator(self, prefix=b'', reverse=False):
|
|
||||||
return LMDB.Iterator(self.db, self.env, prefix, reverse)
|
|
||||||
|
|
||||||
class Iterator:
|
|
||||||
def __init__(self, db, env, prefix, reverse):
|
|
||||||
self.transaction = env.begin(db=db)
|
|
||||||
self.transaction.__enter__()
|
|
||||||
self.db = db
|
|
||||||
self.prefix = prefix
|
|
||||||
self.reverse = reverse
|
|
||||||
self._stop = False
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
self.iterator = LMDB.module.Cursor(self.db, self.transaction)
|
|
||||||
prefix = self.prefix
|
|
||||||
if self.reverse:
|
|
||||||
# Go to the first value after the prefix
|
|
||||||
prefix = increment_byte_string(prefix)
|
|
||||||
self.iterator.set_range(prefix)
|
|
||||||
if not self.iterator.key().startswith(self.prefix) and self.reverse:
|
|
||||||
# Go back to the first item starting with the prefix
|
|
||||||
self.iterator.prev()
|
|
||||||
return self
|
|
||||||
|
|
||||||
def __next__(self):
|
|
||||||
k, v = self.iterator.item()
|
|
||||||
if not k.startswith(self.prefix) or self._stop:
|
|
||||||
# We're already ahead of the prefix
|
|
||||||
self.transaction.__exit__()
|
|
||||||
raise StopIteration
|
|
||||||
next = self.iterator.next \
|
|
||||||
if not self.reverse else self.iterator.prev
|
|
||||||
# Stop after the next value if we're at the end of the DB
|
|
||||||
self._stop = not next()
|
|
||||||
return k, v
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user