2013-02-02 165 views
1

我有很多類都做同樣的事情:他們在構建過程中收到一個標識符(DB中的PK),然後從DB加載。 我想緩存這些類的實例,以最大限度地減少對數據庫的調用。當緩存達到臨界尺寸時,應放棄最近訪問過的緩存對象。緩存和內存使用

緩存實際上似乎工作正常,但不知何故我無法確定緩存的內存使用情況(在#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 

這裏的一些東西,值得注意的是:

  • 一個:空列表的大小爲72
  • B:包含1的列表的大小更多是8個字節
  • C1的大小不是8個字節。造成這種奇怪的原因是1作爲唯一實體與列表分開存在,因此C行返回實體的大小,而B返回空列表的大小加上對該實體的引用。
  • d:這是這樣一個空列表的大小加上一個參考,以不同的列表
  • è:空單加兩所引用= 88個字節

我試圖在這裏得到的是getsizeof只能幫助你獲得大小的東西。你需要知道事物的大小以及事物引用的大小。這聽起來像遞歸。

看看這個食譜,它可能會幫助你:http://code.activestate.com/recipes/546530/