From df28f32b8bcd8bd6f260d31ee18466ac54cb9ca8 Mon Sep 17 00:00:00 2001 From: Sagar Vora Date: Wed, 8 Jun 2022 10:19:11 +0000 Subject: [PATCH] perf: ~90% faster `frappe.get_cached_doc` (#17107) --- frappe/__init__.py | 17 ++++++++++++----- frappe/utils/redis_wrapper.py | 4 +--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/frappe/__init__.py b/frappe/__init__.py index 00ed147c2c..cee264c108 100644 --- a/frappe/__init__.py +++ b/frappe/__init__.py @@ -1040,15 +1040,21 @@ def get_cached_doc(*args, **kwargs): if doc := cache().hget("document_cache", key): return _respond(doc, True) - # Not found in local/redis, fetch from DB and store in cache + # Not found in local/redis, fetch from DB doc = get_doc(*args, **kwargs) - # Store in redis cache - key = get_document_cache_key(doc.doctype, doc.name) + # Store in cache + if not key: + key = get_document_cache_key(doc.doctype, doc.name) local.document_cache[key] = doc - # Avoid setting in local.cache since there's separate cache - cache().hset("document_cache", key, doc.as_dict(), cache_locally=False) + + # Avoid setting in local.cache since we're already using local.document_cache above + # Try pickling the doc object as-is first, else fallback to doc.as_dict() + try: + cache().hset("document_cache", key, doc, cache_locally=False) + except Exception: + cache().hset("document_cache", key, doc.as_dict(), cache_locally=False) return doc @@ -1124,6 +1130,7 @@ def get_doc(*args, **kwargs): if key := can_cache_doc(args): if key in local.document_cache: local.document_cache[key] = doc + if cache().hexists("document_cache", key): cache().hset("document_cache", key, doc.as_dict()) diff --git a/frappe/utils/redis_wrapper.py b/frappe/utils/redis_wrapper.py index 3f364821d1..06480f0b7b 100644 --- a/frappe/utils/redis_wrapper.py +++ b/frappe/utils/redis_wrapper.py @@ -159,9 +159,7 @@ class RedisWrapper(redis.Redis): # set in local if cache_locally: - if _name not in frappe.local.cache: - frappe.local.cache[_name] = {} - frappe.local.cache[_name][key] = value + frappe.local.cache.setdefault(_name, {})[key] = value # set in redis try: