[IMP] core: manage registries via an LRU.
authorChristophe Simonis <chs@odoo.com>
Wed, 29 Oct 2014 17:28:07 +0000 (18:28 +0100)
committerChristophe Simonis <chs@odoo.com>
Wed, 29 Oct 2014 17:28:07 +0000 (18:28 +0100)
When working with a large number of databases, the memory allocated to
registries wasn't limited, resulting to waste memory (especially in the
longpolling worker, which is not recycled).
The size of the LRU is depending on the soft limit configured for
workers.

openerp/modules/registry.py
openerp/tools/func.py

index 679fae0..34672c4 100644 (file)
 
 """
 from collections import Mapping
-from contextlib import contextmanager
 import logging
+import os
 import threading
 
 import openerp
 from .. import SUPERUSER_ID
-from openerp.tools import assertion_report, lazy_property
+from openerp.tools import assertion_report, lazy_property, classproperty, config
+from openerp.tools.lru import LRU
 
 _logger = logging.getLogger(__name__)
 
@@ -259,12 +260,27 @@ class RegistryManager(object):
         registries (essentially database connection/model registry pairs).
 
     """
-    # Mapping between db name and model registry.
-    # Accessed through the methods below.
-    registries = {}
+    _registries = None
     _lock = threading.RLock()
     _saved_lock = None
 
+    @classproperty
+    def registries(cls):
+        if cls._registries is None:
+            size = config.get('registry_lru_size', None)
+            if not size:
+                # Size the LRU depending of the memory limits
+                if os.name != 'posix':
+                    # cannot specify the memory limit soft on windows...
+                    size = 42
+                else:
+                    # On average, a clean registry take 25MB of memory + cache
+                    avgsz = 30 * 1024 * 1024
+                    size = int(config['limit_memory_soft'] / avgsz)
+
+            cls._registries = LRU(size)
+        return cls._registries
+
     @classmethod
     def lock(cls):
         """ Return the current registry lock. """
index baeae0b..0a36166 100644 (file)
@@ -20,7 +20,7 @@
 #
 ##############################################################################
 
-__all__ = ['synchronized', 'lazy_property']
+__all__ = ['synchronized', 'lazy_property', 'classproperty']
 
 from functools import wraps
 from inspect import getsourcefile
@@ -103,4 +103,12 @@ def compose(a, b):
         return a(b(*args, **kwargs))
     return wrapper
 
+
+class _ClassProperty(property):
+    def __get__(self, cls, owner):
+        return self.fget.__get__(None, owner)()
+
+def classproperty(func):
+    return _ClassProperty(classmethod(func))
+
 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: