Add model batch removal optimization for filtering
This commit is contained in:
@@ -58,7 +58,7 @@ class ModelFilter(ModelProxy):
|
||||
take_out = []
|
||||
bring_back = []
|
||||
|
||||
for key, item in self.items():
|
||||
for key, item in sorted(self.items(), key=lambda kv: kv[1]):
|
||||
if not self.accept_item(item):
|
||||
take_out.append(key)
|
||||
|
||||
@@ -66,8 +66,9 @@ class ModelFilter(ModelProxy):
|
||||
if self.accept_item(item):
|
||||
bring_back.append(key)
|
||||
|
||||
for key in take_out:
|
||||
self.filtered_out[key] = self.pop(key)
|
||||
with self.batch_remove():
|
||||
for key in take_out:
|
||||
self.filtered_out[key] = self.pop(key)
|
||||
|
||||
for key in bring_back:
|
||||
self[key] = self.filtered_out.pop(key)
|
||||
|
@@ -1,6 +1,8 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
|
||||
import itertools
|
||||
from bisect import bisect
|
||||
from contextlib import contextmanager
|
||||
from threading import RLock
|
||||
from typing import (
|
||||
TYPE_CHECKING, Any, Dict, Iterator, List, MutableMapping, Optional,
|
||||
@@ -42,6 +44,8 @@ class Model(MutableMapping):
|
||||
|
||||
self.take_items_ownership: bool = True
|
||||
|
||||
self._active_batch_remove_indice: Optional[List[int]] = None
|
||||
|
||||
if self.sync_id:
|
||||
self.instances[self.sync_id] = self
|
||||
|
||||
@@ -144,7 +148,10 @@ class Model(MutableMapping):
|
||||
proxy.source_item_deleted(self, key)
|
||||
|
||||
if self.sync_id:
|
||||
ModelItemDeleted(self.sync_id, index)
|
||||
if self._active_batch_remove_indice is None:
|
||||
ModelItemDeleted(self.sync_id, index)
|
||||
else:
|
||||
self._active_batch_remove_indice.append(index)
|
||||
|
||||
|
||||
def __iter__(self) -> Iterator:
|
||||
@@ -170,3 +177,18 @@ class Model(MutableMapping):
|
||||
new = type(self)(sync_id=sync_id)
|
||||
new.update(self)
|
||||
return new
|
||||
|
||||
|
||||
@contextmanager
|
||||
def batch_remove(self):
|
||||
try:
|
||||
self._active_batch_remove_indice = []
|
||||
yield None
|
||||
finally:
|
||||
indice = self._active_batch_remove_indice
|
||||
groups = [list(group) for item, group in itertools.groupby(indice)]
|
||||
|
||||
for grp in groups:
|
||||
ModelItemDeleted(self.sync_id, index=grp[0], count=len(grp))
|
||||
|
||||
self._active_batch_remove_indice = None
|
||||
|
@@ -43,6 +43,7 @@ class ModelProxy(Model):
|
||||
|
||||
def source_cleared(self, source: Model) -> None:
|
||||
if self.accept_source(source):
|
||||
for source_sync_id, key in self.copy():
|
||||
if source_sync_id == source.sync_id:
|
||||
del self[source_sync_id, key]
|
||||
with self.batch_remove():
|
||||
for source_sync_id, key in self.copy():
|
||||
if source_sync_id == source.sync_id:
|
||||
del self[source_sync_id, key]
|
||||
|
@@ -82,6 +82,7 @@ class ModelItemDeleted(ModelEvent):
|
||||
"""Indicate the removal of a `ModelItem` from a `Backend` `Model`."""
|
||||
|
||||
index: int = field()
|
||||
count: int = 1
|
||||
|
||||
|
||||
@dataclass
|
||||
|
Reference in New Issue
Block a user