Skip to content

Commit eb06528

Browse files
committed
stored_dict:
- cache self.path - add lru cache
1 parent 4d6a7e2 commit eb06528

1 file changed

Lines changed: 22 additions & 6 deletions

File tree

electrum/stored_dict.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from typing import Any, Optional, Tuple, Union, Iterator, Iterable, List, Sequence
33
from .logging import Logger
44

5+
from .lrucache import LRUCache
56

67
FLEX_KEY = str | int | None
78
_RaiseKeyError = object() # singleton for no-default behavior
@@ -99,6 +100,7 @@ class BaseStoredObject:
99100
_key: FLEX_KEY = None
100101
_parent: Optional['BaseStoredObject'] = None
101102
_lock: threading.RLock = None
103+
_path = None
102104

103105
def set_db(self, db):
104106
self._db = db
@@ -116,24 +118,29 @@ def lock(self):
116118

117119
@property
118120
def path(self) -> Sequence[FLEX_KEY] | None:
121+
if self._path is not None:
122+
return self._path
119123
# return None iff we are pruned from root
120124
x = self
121125
s = [x._key]
122126
while x._parent is not None:
123127
x = x._parent
124128
s = [x._key] + s
125129
if x._key != '':
126-
return None
127-
assert self._db is not None
128-
return s
130+
s = []
131+
#return None
132+
else:
133+
assert self._db is not None
134+
self._path = s
135+
return self._path
129136

130137

131138
class StoredObject(BaseStoredObject):
132139
"""for attr.s objects """
133140

134141
def __setattr__(self, key: str, value):
135142
assert isinstance(key, str), repr(key)
136-
if self.path and not key.startswith('_'):
143+
if not key.startswith('_') and self.path:
137144
if value != getattr(self, key):
138145
self._db.replace(self.path, key, value)
139146
object.__setattr__(self, key, value)
@@ -163,6 +170,7 @@ def __init__(self, db: BaseDB, key: FLEX_KEY, parent):
163170
self._parent = parent
164171
self._key = key_to_str(key)
165172
self._should_convert = True
173+
self._cache = LRUCache(maxsize=100)
166174

167175
def should_convert(self):
168176
return self._parent._should_convert if self._parent is not None else self._should_convert
@@ -176,6 +184,8 @@ def get_dict(self, key) -> 'StoredDict':
176184

177185
def __getitem__(self, key: FLEX_KEY) -> Any:
178186
key = key_to_str(key)
187+
if cached := self._cache.get(key):
188+
return cached
179189
value = self._db.get(self.path, key)
180190
if not self.should_convert():
181191
if isinstance(value, dict):
@@ -187,9 +197,10 @@ def __getitem__(self, key: FLEX_KEY) -> Any:
187197
value.set_db(self._db)
188198
value.set_parent(key=key, parent=self)
189199
elif isinstance(value, list):
190-
return StoredList(self._db, key=key, parent=self)
200+
value = StoredList(self._db, key=key, parent=self)
191201
elif isinstance(value, dict):
192-
return StoredDict(self._db, key=key, parent=self)
202+
value = StoredDict(self._db, key=key, parent=self)
203+
self._cache[key] = value
193204
return value
194205

195206
def __setitem__(self, key: FLEX_KEY, value: Any) -> None:
@@ -201,10 +212,14 @@ def __setitem__(self, key: FLEX_KEY, value: Any) -> None:
201212
if isinstance(value, StoredDict):
202213
raise Exception('trying to set StoredDict')
203214
self._db.put(self.path, key, value)
215+
if key in self._cache:
216+
del self._cache[key]
204217

205218
def __delitem__(self, key: FLEX_KEY) -> None:
206219
key = key_to_str(key)
207220
self._db.remove(self.path, key)
221+
if key in self._cache:
222+
del self._cache[key]
208223

209224
def __iter__(self) -> Iterator[str]:
210225
return self._db.iter_keys(self.path)
@@ -239,6 +254,7 @@ def get(self, key: FLEX_KEY, default: Any = None) -> Any:
239254

240255
def clear(self) -> None:
241256
self._db.clear(self.path)
257+
self._cache.clear()
242258

243259
def pop(self, key: FLEX_KEY, default: Any = _RaiseKeyError) -> Any:
244260
try:

0 commit comments

Comments
 (0)