[IMP] core: manage registries via an LRU.

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.
This commit is contained in:
Christophe Simonis 2014-10-29 18:28:07 +01:00
parent 82588faa71
commit cc4fba6089
2 changed files with 30 additions and 6 deletions

View File

@ -23,13 +23,14 @@
"""
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. """

View 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: