1

私には、すべて同じことを行うクラスがたくさんあります。それらは、構築中に識別子(DB内のPK)を受け取り、DBからロードされます。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面白い値を返します。

キャッシュされたすべてのオブジェクトの実際のメモリ使用量を確認するにはどうすればよいですか?

4

1 に答える 1

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:したがって、これは空のリストのサイズに別のリストへの1つの参照を加えたものです
  • E:空のリストと2つの参照=88バイト

ここで私が取得しようとしているのは、getsizeofは物のサイズを取得するのに役立つだけだということです。あなたは物事のサイズだけでなく、それらのものが参照するもののサイズを取得する必要があります。これは再帰のようなにおいがします。

このレシピをチェックしてください、それはあなたを助けるかもしれません: http: //code.activestate.com/recipes/546530/

于 2013-02-02T09:53:51.277 に答える