summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2021-05-13 15:53:02 +0200
committerAnton Khirnov <anton@khirnov.net>2021-05-13 15:53:02 +0200
commit5045ee68b6caf8b51121f6f85e4dfcae5e5a0ba0 (patch)
treedc83deb3298920c0e57d338dba689950b0f95695
parent954d79c47d4c123d1dafc2c670d79685b7ce84b1 (diff)
db: implement an email message cachemsg_cache
Not in master because it doesn't seem to be the bottleneck, didn't check whether the difference is measurable.
-rw-r--r--alot/db/manager.py31
-rw-r--r--alot/db/message.py3
2 files changed, 32 insertions, 2 deletions
diff --git a/alot/db/manager.py b/alot/db/manager.py
index efd70e70..9d76ddeb 100644
--- a/alot/db/manager.py
+++ b/alot/db/manager.py
@@ -3,8 +3,10 @@
# For further details see the COPYING file
import asyncio
+from collections import OrderedDict
from concurrent.futures import ThreadPoolExecutor
from contextlib import closing
+import email
from functools import partial, partialmethod
import logging
import os
@@ -112,6 +114,31 @@ class _DBWriteList:
def __str__(self):
return '%s:%s' % (self.__class__.__name__, self._ops)
+class _EmailCache:
+ _cache = None
+
+ def __init__(self, max_size = 128):
+ self._cache = OrderedDict()
+ self._max_size = max_size
+
+ def get(self, path):
+ with open(path, 'rb') as f:
+ mtime = os.stat(f.fileno()).st_mtime
+
+ mtime_cached, mail = self._cache.pop(path, (None, None))
+ if mtime_cached != mtime:
+ mail = email.message_from_bytes(f.read(), policy = email.policy.SMTP)
+ logging.info('loading from disk')
+ else:
+ logging.info('reading from cache')
+
+ # update the cache
+ if len(self._cache) >= self._max_size:
+ self._cache.popitem(last = False)
+ self._cache[path] = (mtime, mail)
+
+ return mail
+
class DBManager:
"""
Keeps track of your index parameters, maintains a write-queue and
@@ -130,6 +157,8 @@ class DBManager:
_write_task = None
_write_queue = None
+ _email_cache = None
+
def __init__(self, loop, path=None, ro=False):
"""
:param path: absolute path to the notmuch index
@@ -148,6 +177,8 @@ class DBManager:
self._exclude_tags = frozenset(settings.get('exclude_tags'))
self._property_tags = frozenset(settings.get('property_tags'))
+ self._email_cache = _EmailCache()
+
def _db_ro(self):
return closing(Database(path = self.path, mode = Database.MODE.READ_ONLY))
diff --git a/alot/db/message.py b/alot/db/message.py
index 74139315..f7aea829 100644
--- a/alot/db/message.py
+++ b/alot/db/message.py
@@ -459,8 +459,7 @@ class Message:
@cached_property
def _email(self):
try:
- with open(self.filename, 'rb') as f:
- mail = email.message_from_bytes(f.read(), policy = email.policy.SMTP)
+ mail = self._dbman._email_cache.get(self.filename)
except IOError:
warning = b"Subject: Caution!\n"\
b"Message file is no longer accessible:\n%s" % self.filename