Changeset 666 for branches


Ignore:
Timestamp:
05/28/13 21:26:34 (3 years ago)
Author:
mmckerns
Message:

sync'd memoize with cache; added cache method in memoize

Location:
branches/decorate
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • branches/decorate/memoize.py

    r665 r666  
    22decorators that cache results to memory, to file, or to a database 
    33""" 
     4from functools import update_wrapper, wraps as functools_wraps 
     5from rounding import deep_round, simple_round 
     6from archives import archive_dict 
    47from keymaps import stringmap 
    5 from archives import archive_dict 
    6 from rounding import deep_round, simple_round 
     8from cache import _CacheInfo 
    79 
    810__all__ = ['memoize', 'memoized'] 
     
    1113#XXX: memoized fails when decorating a class method ??? 
    1214 
     15#XXX: essentially this is: cache.inf_cache(keymap=stringmap(flat=False)) 
    1316def memoized(cache=None, keymap=None, tol=None, deep=False): 
    1417    """Decorator that memoizes a function's return value each time it is called. 
     
    2326    deep = boolean for rounding depth (default is False, i.e. 'shallow') 
    2427    """ 
    25     if keymap is None: keymap = stringmap(flat=False) 
     28    maxsize = None 
     29 
     30    if keymap is None: keymap = stringmap(flat=False) #XXX: hashmap(flat=True) 
    2631    if cache is None: cache = archive_dict() 
    2732    elif type(cache) is dict: cache = archive_dict(cache) 
     
    3641        return (args, kwds) 
    3742 
    38     def dec(f): 
    39         def func(*args, **kwds): 
     43    def decorating_function(user_function): 
     44        _len = len                      # localize the global len() function 
     45        stats = [0, 0, 0]               # make statistics updateable non-locally 
     46        HIT, MISS, LOAD = 0, 1, 2       # names for the stats fields 
     47        _len = len                      # localize the global len() function 
     48       #lock = RLock()                  # linkedlist updates aren't threadsafe 
     49 
     50        def wrapper(*args, **kwds): 
    4051            try: 
    4152                _args, _kwds = rounded_args(*args, **kwds) 
    42                 argstr = keymap(*_args, **_kwds) 
    43                 if cache.has_key(argstr): 
    44                     return cache[argstr] 
    45                 if cache.archived(): 
    46                     cache.load(argstr) 
    47                     if cache.has_key(argstr): 
    48                         return cache[argstr] 
    49                 res = f(*args, **kwds) 
    50                 cache[argstr] = res  #XXX: any automated dump to archive? 
    51                 return res 
     53                key = keymap(*_args, **_kwds) 
     54 
     55                try: 
     56                    # get cache entry 
     57                    result = cache[key] 
     58                    stats[HIT] += 1 
     59                except KeyError: 
     60                    # if not in cache, look in archive 
     61                    if cache.archived(): 
     62                        cache.load(key) 
     63                    try: 
     64                        result = cache[key] 
     65                        stats[LOAD] += 1 
     66                    except KeyError: 
     67                        # if not found, then compute 
     68                        result = user_function(*args, **kwds) 
     69                        cache[key] = result 
     70                        stats[MISS] += 1 
     71                    #XXX:  NO cache purge... 
    5272            except: #TypeError 
    53                 return f(*args, **kwds) 
    54         func.cache = cache 
    55         return func 
    56     return dec 
     73                result = user_function(*args, **kwds) 
     74            return result 
     75 
     76        def archive(obj): 
     77            """Replace the cache archive""" 
     78            cache.archive = obj 
     79 
     80        def __get_cache(): 
     81            """Get the cache""" 
     82            return cache 
     83 
     84        def clear(keepstats=False): 
     85            """Clear the cache and statistics""" 
     86            cache.clear() 
     87            if not keepstats: stats[:] = [0, 0, 0] 
     88 
     89        def info(): 
     90            """Report cache statistics""" 
     91            return _CacheInfo(stats[HIT], stats[MISS], stats[LOAD], maxsize, len(cache)) 
     92 
     93        # interface 
     94        wrapper.__wrapped__ = user_function 
     95        wrapper.info = info 
     96        wrapper.clear = clear 
     97        wrapper.load = cache.load 
     98        wrapper.dump = cache.dump 
     99        wrapper.archive = archive 
     100        wrapper.archived = cache.archived 
     101        wrapper.__cache__ = __get_cache 
     102        return update_wrapper(wrapper, user_function) 
     103 
     104    return decorating_function 
    57105 
    58106 
     
    64112    """ 
    65113    def __init__(self, cache=None, keymap=None, tol=None, deep=False): 
    66 #       self.func = func 
    67         if keymap is None: keymap = stringmap(flat=False) 
     114        self.__maxsize = None 
     115        if keymap is None: keymap = stringmap(flat=False) #XXX: hashmap(True) ? 
    68116        if cache is None: cache = archive_dict() 
    69117        elif type(cache) is dict: cache = archive_dict(cache) 
    70         self.cache = cache 
     118        self.__cache = cache 
    71119        self.__keymap = keymap 
    72120 
     
    80128        return 
    81129 
    82     def __call__(self, func): 
    83         self.func = func 
    84         import functools 
    85         @functools.wraps(func) 
    86         def dec(*args, **kwds): 
     130    def __call__(self, user_function): #XXX: i.e. 'decorating_function' 
     131        stats = [0, 0, 0]               # make statistics updateable non-locally 
     132        HIT, MISS, LOAD = 0, 1, 2       # names for the stats fields 
     133 
     134        def wrapper(*args, **kwds): 
    87135            try: 
    88136                _args, _kwds = self.__rounded_args(*args, **kwds) 
    89                 argstr = self.__keymap(*_args, **_kwds) 
    90                 if self.cache.has_key(argstr): 
    91                     return self.cache[argstr] 
    92                 if self.cache.archived(): 
    93                     self.cache.load(argstr) 
    94                     if self.cache.has_key(argstr): 
    95                         return self.cache[argstr] 
    96                 res = self.func(*args, **kwds) 
    97                 self.cache[argstr] = res 
    98                 return res 
     137                key = self.__keymap(*_args, **_kwds) 
     138 
     139                try: 
     140                    # get cache entry 
     141                    result = self.__cache[key] 
     142                    stats[HIT] += 1 
     143                except KeyError: 
     144                    # if not in cache, look in archive 
     145                    if self.__cache.archived(): 
     146                        self.__cache.load(key) 
     147                    try: 
     148                        result = self.__cache[key] 
     149                        stats[LOAD] += 1 
     150                    except KeyError: 
     151                        # if not found, then compute 
     152                        result = user_function(*args, **kwds) 
     153                        self.__cache[key] = result 
     154                        stats[MISS] += 1 
     155                    #XXX:  NO cache purge... 
    99156            except: #TypeError 
    100                 return self.func(*args, **kwds) 
    101         return dec 
     157                result = user_function(*args, **kwds) 
     158            return result 
    102159 
    103     def __repr__(self): 
    104         """Return the function's docstring.""" 
    105         return self.func.__doc__ 
     160        def archive(obj): 
     161            """Replace the cache archive""" 
     162            self.__cache.archive = obj 
     163 
     164        def __get_cache(): 
     165            """Get the cache""" 
     166            return self.__cache 
     167 
     168        def clear(keepstats=False): 
     169            """Clear the cache and statistics""" 
     170            self.__cache.clear() 
     171            if not keepstats: stats[:] = [0, 0, 0] 
     172 
     173        def info(): 
     174            """Report cache statistics""" 
     175            return _CacheInfo(stats[HIT], stats[MISS], stats[LOAD], self.__maxsize, len(self.__cache)) 
     176 
     177        # interface 
     178        wrapper.__wrapped__ = user_function 
     179        wrapper.info = info 
     180        wrapper.clear = clear 
     181        wrapper.load = self.__cache.load 
     182        wrapper.dump = self.__cache.dump 
     183        wrapper.archive = archive 
     184        wrapper.archived = self.__cache.archived 
     185        wrapper.__cache__ = __get_cache 
     186        return update_wrapper(wrapper, user_function) 
     187 
     188#   def __repr__(self): 
     189#       """Return the function's docstring.""" 
     190#       return self.func.__doc__ 
    106191 
    107192    def __get__(self, obj, objtype): 
  • branches/decorate/test_cached_memoize.py

    r665 r666  
    1313    return fibonacci(n-1) + fibonacci(n-2) 
    1414 
    15 fibonacci.cache.archive = file_archive('fibonacci.pkl') 
    16 fibonacci.cache.load() 
     15fibonacci.archive(file_archive('fibonacci.pkl')) 
     16fibonacci.load() 
    1717 
    1818print fibonacci(7) 
    1919print fibonacci(9) 
    2020 
    21 fibonacci.cache.dump() 
     21fibonacci.dump() 
    2222 
    2323 
  • branches/decorate/test_memoize.py

    r665 r666  
    118118add(1,2) 
    119119add(1,3) 
    120 print "db_cache = %s" % add.cache 
     120print "db_cache = %s" % add.__cache__() 
    121121 
    122122@memoized(cache=dict()) 
     
    126126add(1,2) 
    127127add(1,3) 
    128 print "dict_cache = %s" % add.cache 
     128print "dict_cache = %s" % add.__cache__() 
    129129 
    130 @memoized(cache=add.cache) 
     130@memoized(cache=add.__cache__()) 
    131131def add(x,y): 
    132132    return x+y 
    133133add(1,2) 
    134134add(2,2) 
    135 print "re_dict_cache = %s" % add.cache 
     135print "re_dict_cache = %s" % add.__cache__() 
    136136 
    137137@memoized(keymap=dumps) 
     
    141141add(1,2) 
    142142add(1,3) 
    143 print "pickle_dict_cache = %s" % add.cache 
     143print "pickle_dict_cache = %s" % add.__cache__() 
    144144 
    145145 
  • branches/decorate/test_timed_monitor.py

    r664 r666  
    174174  print " upper bounds: %s" % upper_bounds 
    175175# print " ..." 
    176   try: model.cache.load() 
     176  try: model.load() 
    177177  except: pass 
    178178  diameter = UQ(RVstart,RVend,lower_bounds,upper_bounds) 
    179   try: model.cache.dump() 
     179  try: model.dump() 
    180180  except: pass 
    181181 
Note: See TracChangeset for help on using the changeset viewer.