[FIX] registry: use a weak dictionary for model_cache to avoid memory leaks

The class attribute `model_cache` refers to model classes, which refer to their
own registry.  This cache potentially keeps all past registries alive!
This commit is contained in:
Raphael Collet
2017-03-21 15:50:20 +01:00
parent 3b774ee329
commit c9edb9dccb
2 changed files with 5 additions and 7 deletions
+1 -1
View File
@@ -2817,7 +2817,7 @@ class BaseModel(object):
self._add_magic_fields()
cls._proper_fields = set(cls._fields)
cls.pool.model_cache[cls._model_cache_key] = cls
cls.pool.model_cache[cls._model_cache_key] = cls
# 2. add custom fields
self._add_manual_fields(partial)
+4 -6
View File
@@ -7,6 +7,7 @@
from collections import Mapping, defaultdict, deque
from contextlib import closing
from operator import attrgetter
from weakref import WeakValueDictionary
import logging
import os
import threading
@@ -30,6 +31,9 @@ class Registry(Mapping):
_lock = threading.RLock()
_saved_lock = None
# a cache for model classes, indexed by their base classes
model_cache = WeakValueDictionary()
@lazy_classproperty
def registries(cls):
""" A mapping from database names to registries. """
@@ -177,12 +181,6 @@ class Registry(Mapping):
""" Add or replace a model in the registry."""
self.models[model_name] = model
@lazy_classproperty
def model_cache(cls):
""" A cache for model classes, indexed by their base classes. """
# we cache 256 classes per registry on average
return LRU(cls.registries.count * 256)
@lazy_property
def field_sequence(self):
""" Return a function mapping a field to an integer. The value of a