Prevent single file storage from performing unnecessary N^2 loop

For single file storage we wrap the logic of get_multi with the
at_once context manager so that `self.list()` (which is called by
`self.get()`) actually caches the items rather than re-computing
them at every call.

This should largely mitigate the performance issue describe at
https://github.com/pimutils/vdirsyncer/issues/818 . The issue
discussion also contains more background about this patch.
This commit is contained in:
Enrico Guiraud 2023-03-09 17:59:20 -06:00
parent 54a90aa5dd
commit 85ae33955f
No known key found for this signature in database
GPG key ID: 7D1B732A95F873F2

View file

@ -4,6 +4,7 @@ import functools
import glob
import logging
import os
from typing import Iterable
from atomicwrites import atomic_write
@ -11,6 +12,7 @@ from .. import exceptions
from ..utils import checkfile
from ..utils import expand_path
from ..utils import get_etag_from_file
from ..utils import uniq
from ..vobject import Item
from ..vobject import join_collection
from ..vobject import split_collection
@ -132,6 +134,12 @@ class SingleFileStorage(Storage):
except KeyError:
raise exceptions.NotFoundError(href)
async def get_multi(self, hrefs: Iterable[str]):
async with self.at_once():
for href in uniq(hrefs):
item, etag = await self.get(href)
yield href, item, etag
@_writing_op
async def upload(self, item):
href = item.ident