From 975fa5e783b341d6a35d1b80e125a799e79a8c97 Mon Sep 17 00:00:00 2001 From: Marko Toplak Date: Fri, 26 Jul 2024 14:40:16 +0200 Subject: [PATCH] Domain __eq__: only cache 10 domains --- Orange/data/domain.py | 11 ++++++++++- Orange/tests/test_domain.py | 19 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/Orange/data/domain.py b/Orange/data/domain.py index 18cb99eeecb..4dffd423225 100644 --- a/Orange/data/domain.py +++ b/Orange/data/domain.py @@ -170,7 +170,7 @@ def __init__(self, attributes, class_vars=None, metas=None, source=None): self.anonymous = False self._hash = None # cache for __hash__() - self._eq_cache = IDWeakrefCache({}) # cache for __eq__() + self._eq_cache = IDWeakrefCache(_LRS10Dict()) # cache for __eq__() def _ensure_indices(self): if self._indices is None: @@ -536,3 +536,12 @@ def __hash__(self): if self._hash is None: self._hash = hash(self.attributes) ^ hash(self.class_vars) ^ hash(self.metas) return self._hash + + +class _LRS10Dict(dict): + """ A small "least recently stored" (not LRU) dict """ + + def __setitem__(self, key, value): + if len(self) >= 10: + del self[next(iter(self))] + super().__setitem__(key, value) diff --git a/Orange/tests/test_domain.py b/Orange/tests/test_domain.py index 650f96813b1..b1c8227e90e 100644 --- a/Orange/tests/test_domain.py +++ b/Orange/tests/test_domain.py @@ -488,6 +488,25 @@ def __hash__(self): domain1._eq_cache[(domain2,)] = False # pylint: disable=protected-access self.assertFalse(domain1 == domain2) + def test_eq_cache_not_grow(self): + var = ContinuousVariable('var') + domain = Domain([var]) + domains = [Domain([var]) for _ in range(10)] + for d in domains: + self.assertTrue(domain == d) + + # __eq__ results to all ten domains should be cached + for d in domains: + domain._eq_cache[(d,)] # pylint: disable=protected-access + + dn = Domain([var]) + self.assertTrue(domain == dn) + # the last compared domain should be cached + domain._eq_cache[(dn,)] # pylint: disable=protected-access + # but the first compared should be lost in cache + with self.assertRaises(KeyError): + domain._eq_cache[(domains[0],)] # pylint: disable=protected-access + def test_domain_conversion_is_fast_enough(self): attrs = [ContinuousVariable("f%i" % i) for i in range(10000)] class_vars = [ContinuousVariable("c%i" % i) for i in range(10)]