Кэширование и использование памяти
У меня есть много классов, которые все делают одно и то же: они получают идентификатор (PK в БД) во время создания, а затем загружаются из БД. Я пытаюсь кэшировать экземпляры этих классов, чтобы минимизировать обращения к БД. Когда кэш достигает критического размера, он должен отбросить те кешированные объекты, к которым обращались не так давно.
Кажется, что кеширование работает нормально, но почему-то я не могу определить использование памяти кешем (в строке после #Next line doesn't do what I expected
).
Мой код до сих пор:
#! /usr/bin/python3.2
from datetime import datetime
import random
import sys
class Cache:
instance = None
def __new__ (cls):
if not cls.instance:
cls.instance = super ().__new__ (cls)
cls.instance.classes = {}
return cls.instance
def getObject (self, cls, ident):
if cls not in self.classes: return None
cls = self.classes [cls]
if ident not in cls: return None
return cls [ident]
def cache (self, object):
#Next line doesn't do what I expected
print (sys.getsizeof (self.classes) )
if object.__class__ not in self.classes:
self.classes [object.__class__] = {}
cls = self.classes [object.__class__]
cls [object.ident] = (object, datetime.now () )
class Cached:
def __init__ (self, cache):
self.cache = cache
def __call__ (self, cls):
cls.cache = self.cache
oNew = cls.__new__
def new (cls, ident):
cached = cls.cache ().getObject (cls, ident)
if not cached: return oNew (cls, ident)
cls.cache ().cache (cached [0] )
return cached [0]
cls.__new__ = new
def init (self, ident):
if hasattr (self, 'ident'): return
self.ident = ident
self.load ()
cls.__init__ = init
oLoad = cls.load
def load (self):
oLoad (self)
self.cache ().cache (self)
cls.load = load
return cls
@Cached (Cache)
class Person:
def load (self):
print ('Expensive call to DB')
print ('Loading Person {}'.format (self.ident) )
#Just simulating
self.name = random.choice ( ['Alice', 'Bob', 'Mallroy'] )
@Cached (Cache)
class Animal:
def load (self):
print ('Expensive call to DB')
print ('Loading Animal {}'.format (self.ident) )
#Just simulating
self.species = random.choice ( ['Dog', 'Cat', 'Iguana'] )
sys.getsizeof
возвращает забавные значения.
Как определить фактическое использование памяти всеми кэшированными объектами?
1 ответ
getsizeof
довольно сложно, вот иллюстрация факта:
getsizeof([]) # returns 72 ------------A
getsizeof([1,]) # returns 80 ------------B
getsizeof(1) # returns 24 ------------C
getsizeof([[1,],]) # returns 80 ------------D
getsizeof([[1,],1]) # returns 88 ------------E
Вот некоторые вещи, которые стоит отметить:
- A: размер пустого списка составляет 72
- B: размер списка, содержащего
1
на 8 байт больше - C: размер
1
не 8 байтов. Причина этой странности в том, что1
существует отдельно для списка как уникальная сущность, поэтому строка C возвращает размер сущности, а B возвращает размер пустого списка плюс ссылку на эту сущность. - D: Таким образом, это размер пустого списка плюс одна ссылка на другой список
- E: пустой список плюс две ссылки = 88 байт
Я пытаюсь понять, что getizeof может помочь вам получить размеры вещей. Вы должны получить размеры вещей, а также размеры вещей, на которые эти вещи ссылаются. Это пахнет как рекурсия.
посмотрите этот рецепт, он может вам помочь: http://code.activestate.com/recipes/546530/