diff options
author | Anton Khirnov <anton@khirnov.net> | 2021-05-13 15:53:02 +0200 |
---|---|---|
committer | Anton Khirnov <anton@khirnov.net> | 2021-05-13 15:53:02 +0200 |
commit | 5045ee68b6caf8b51121f6f85e4dfcae5e5a0ba0 (patch) | |
tree | dc83deb3298920c0e57d338dba689950b0f95695 | |
parent | 954d79c47d4c123d1dafc2c670d79685b7ce84b1 (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.py | 31 | ||||
-rw-r--r-- | alot/db/message.py | 3 |
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 |