[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:
parent
82588faa71
commit
cc4fba6089
|
@ -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. """
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue