ORM Cache
The Odoo framework provides the ORM Cache decorator with the ability to handle in-memory caches. This recipe explores how to handle function caching.
The classes of this ORM cache are accessible at /odoo/apparatuses/cache.py. To utilize these in any record, you should import them.
From Odoo import tools
After including the class, you can use the ORM cache decorator. Odoo offers different types of in-memory cache decorators. These are described in the sections below.
ormcache
This is the simplest and most commonly used cache decorator. You must pass the names of the arguments on which the method's result depends. Below is an example method using the ormcache decorator.
@tools.ormcache('key')
def _check_data(self, key):
# some code
return result
Calling this method for the first time executes it and returns the result. ormcache stores this result based on the value of the key parameter. Calling the method again with the same key value will serve the result from the cache without actually executing the method.
Method results may depend on environmental attributes. In such cases, you can declare the method like this:
@tools.ormcache('self.env.uid', 'key')
def _check_data(self, key):
# some code
return result
The method specified in this example saves the cache based on the values of the environment user and mode parameters.
ormcache_context
This cache works like ormcache except that it relies on parameters and values in context. The decorator for this cache requires passing a list of parameter names and context keys. For example, you can use ormcache_context if the output of your method depends on the lang and timezone(tz) keys in your context.
@tools.ormcache_context('name', keys=('tz', 'lang'))
def _check_data(self, key):
# some code
return result
The cache in the previous example depends on key arguments and context values.
Ormcache multi
Some methods perform operations on multiple records or IDs. If you want to cache this kind of technique, you can use the ormcache_multi decorator. You really want to pass multiple bounds, and during the function call the ORM will create a cache key by iterating over this bound. This method requires a multi-boundary component as a key to return results in a dictionary-style design. Examine the attached example.
@tools.ormcache_multi('mode', multi='ids')
def _check_data(self, mode,ids):
result = {}
for i in ids:
data = ... # some calculations based on ids
result[i] = data
return result
Suppose you called the previous method with [1,2,3] as IDs. This method returns results in the form {1:... , 2:..., 3:... }. The ORM stores results based on these keys. If I make another call with [1,2,3,4,5] as ids, the method gets [4, 5] as id parameters, so the method does ids 4 and 5 and the rest of the operations. Results are served from the cache.
An ORM cache maintains its cache in dictionary form (cache lookups). The key for this cache is generated based on the signature of the decorated method, and the value is the result. Simply put, if you call a method with parameters x, y and the result of the method is x+y, the cache lookup is {(x, y): x+y}. This means that the next time this method is called with the same parameters, the results will be served directly from this cache. This saves computation time and speeds up the answer.
self.env[model_name].clear_caches()
After flushing the cache, the next invocation of the method will execute the method and store the result in the cache. All subsequent method calls with the same parameters will be served from the cache.
Least Recently Used (LRU)
The ORM cache is a least recently used (LRU) cache. This means that keys in the cache that are not used frequently are removed. Improper use of ORM caching can do more harm than good. For example, if the arguments passed to a method are always different, Odoo will first look in the cache each time before calling the method to calculate. If you want to know how caching works, you can pass the SIGUSR1 signal to the Odoo process.
kill -SIGUSR1 <pid>
Here 674269 is the process ID. After running the command, you can check the ORM cache status in the logs.
kill -SIGUSR1 674269
The percentage in cache is a hit-to-miss ratio. The success rate for results found in the cache. If your cache hit/miss ratio is too low, consider removing his ORM cache from your method.