From 368751b9389ea652cffc7864adef66aac59986d9 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Mon, 4 Feb 2019 13:57:22 +0000 Subject: [IMP] api: avoid `record.id` indirections The cache is quite time critical, as it is accessed millions times when reading multiple fields on hundred of thousands of records. Avoiding indirections and `if` statement when possible speeds up the cache access time. --- odoo/api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'odoo/api.py') diff --git a/odoo/api.py b/odoo/api.py index ca9927739a5..1bf9ba05f90 100644 --- a/odoo/api.py +++ b/odoo/api.py @@ -964,13 +964,13 @@ class Cache(object): def get(self, record, field): """ Return the value of ``field`` for ``record``. """ key = record.env.cache_key(field) - value = self._data[key][field][record.id] + value = self._data[key][field][record._ids[0]] return value.get() if isinstance(value, SpecialValue) else value def set(self, record, field, value): """ Set the value of ``field`` for ``record``. """ key = record.env.cache_key(field) - self._data[key][field][record.id] = value + self._data[key][field][record._ids[0]] = value def remove(self, record, field): """ Remove the value of ``field`` for ``record``. """ -- cgit v1.2.3 From 36551615b7265ad83dbf9d1207ff9ee59b7069f3 Mon Sep 17 00:00:00 2001 From: Denis Ledoux Date: Mon, 4 Feb 2019 14:47:50 +0000 Subject: [IMP] read, cache: faster read by updating the cache by fields instead of updating the cache by records. We use `cr.fetchall()` and `zip` to get the values by field, which is more convenient to be stored in cache. Result of `cr.fetchall()`: ``` [ (3, 'Marc Demo', 'demo@example.com', '032'), (1, 'Mitchell Admin', 'admin@example.com', '001'), ] ``` After being grouped by field: ``` [ [3, 1], ['Marc Demo', 'Mitchell Admin], ['demo@example.com', 'admin@example.com'], ['032', '001'], ] ``` That way we can update the cache of a field for all records at once, by calling the builtin `update` method of `dict` with the `zip` of record ids and corresponding values. This significantly speeds up the storage of field values in the cache. closes odoo/odoo#30817 --- odoo/api.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'odoo/api.py') diff --git a/odoo/api.py b/odoo/api.py index 1bf9ba05f90..7eeeb2ef3b6 100644 --- a/odoo/api.py +++ b/odoo/api.py @@ -55,7 +55,7 @@ from weakref import WeakSet from decorator import decorator from werkzeug.local import Local, release_local -from odoo.tools import frozendict, classproperty +from odoo.tools import frozendict, classproperty, pycompat _logger = logging.getLogger(__name__) @@ -972,6 +972,11 @@ class Cache(object): key = record.env.cache_key(field) self._data[key][field][record._ids[0]] = value + def update(self, records, field, values): + """ Set the values of ``field`` for several ``records``. """ + key = records.env.cache_key(field) + self._data[key][field].update(pycompat.izip(records._ids, values)) + def remove(self, record, field): """ Remove the value of ``field`` for ``record``. """ key = record.env.cache_key(field) -- cgit v1.2.3