From a5fde9a90a8216f70129c20d348f1f615b8842f3 Mon Sep 17 00:00:00 2001 From: Thomas Herve Date: Mon, 22 Oct 2018 14:27:35 +0200 Subject: Override getttext.find to cache result This monkey patches gettext to cache the results of gettext.find. This allows to drastically reduces system calls made over time for checking the existence of mo files, which don't move. Change-Id: I1464f131b90123aab67ef45ae2a2685a3ba111ef --- oslo_i18n/_gettextutils.py | 26 ++++++++++++++++++++++++++ oslo_i18n/tests/test_gettextutils.py | 10 ++++++++++ 2 files changed, 36 insertions(+) diff --git a/oslo_i18n/_gettextutils.py b/oslo_i18n/_gettextutils.py index 9153b36..00028a6 100644 --- a/oslo_i18n/_gettextutils.py +++ b/oslo_i18n/_gettextutils.py @@ -99,3 +99,29 @@ def get_available_languages(domain): _AVAILABLE_LANGUAGES[domain] = result return copy.copy(result) + + +_original_find = gettext.find +_FIND_CACHE = {} + + +def cached_find(domain, localedir=None, languages=None, all=0): + """A version of gettext.find using a cache. + + gettext.find looks for mo files on the disk using os.path.exists. Those + don't tend to change over time, but the system calls pile up with a + long-running service. This caches the result so that we return the same mo + files, and only call find once per domain. + """ + key = (domain, + localedir, + tuple(languages) if languages is not None else None, + all) + if key in _FIND_CACHE: + return _FIND_CACHE[key] + result = _original_find(domain, localedir, languages, all) + _FIND_CACHE[key] = result + return result + + +gettext.find = cached_find diff --git a/oslo_i18n/tests/test_gettextutils.py b/oslo_i18n/tests/test_gettextutils.py index 6a30a95..2eca069 100644 --- a/oslo_i18n/tests/test_gettextutils.py +++ b/oslo_i18n/tests/test_gettextutils.py @@ -129,3 +129,13 @@ class GettextTest(test_base.BaseTestCase): unknown_domain_languages = _gettextutils.get_available_languages('huh') self.assertEqual(1, len(unknown_domain_languages)) self.assertIn('en_US', unknown_domain_languages) + + def test_cached_find(self): + domain = 'my-unique-domain' + key = (domain, None, None, 0) + self.assertNotIn(key, _gettextutils._FIND_CACHE) + gettext.find(domain) + self.assertIn(key, _gettextutils._FIND_CACHE) + _gettextutils._FIND_CACHE[key] = "spoof result" + self.assertEqual("spoof result", gettext.find(domain)) + _gettextutils._FIND_CACHE.pop(key) -- cgit v1.2.1