]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Re-introduction of caching. Not thread-safe against the changing of locale
authorBrett Cannon <bcannon@gmail.com>
Wed, 6 Aug 2003 21:17:09 +0000 (21:17 +0000)
committerBrett Cannon <bcannon@gmail.com>
Wed, 6 Aug 2003 21:17:09 +0000 (21:17 +0000)
in the middle of executing time.strptime .  Added new tests for caching
mechanism; taken from 2.4 branch and tweaked appropriately.

Lib/_strptime.py
Lib/test/test_strptime.py
Misc/NEWS

index ed8ed35373a497ad4d9a9c5d8b7259a588436899..02eacce1059e800bbb3415145ddef7d621175093 100644 (file)
@@ -397,12 +397,28 @@ class TimeRE(dict):
         """Return a compiled re object for the format string."""
         return re_compile(self.pattern(format), IGNORECASE)
 
+# Cached TimeRE; probably only need one instance ever so cache it for performance
+_locale_cache = TimeRE()
+# Cached regex objects; same reason as for TimeRE cache
+_regex_cache = dict()
 
 def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
     """Return a time struct based on the input data and the format string."""
-    time_re = TimeRE()
-    locale_time = time_re.locale_time
-    format_regex = time_re.compile(format)
+    global _locale_cache
+    global _regex_cache
+    locale_time = _locale_cache.locale_time
+    # If the language changes, caches are invalidated, so clear them
+    if locale_time.lang != _getlang():
+        _locale_cache = TimeRE()
+        _regex_cache.clear()
+    format_regex = _regex_cache.get(format)
+    if not format_regex:
+        # Limit regex cache size to prevent major bloating of the module;
+        # The value 5 is arbitrary
+        if len(_regex_cache) > 5:
+            _regex_cache.clear()
+        format_regex = _locale_cache.compile(format)
+        _regex_cache[format] = format_regex
     found = format_regex.match(data_string)
     if not found:
         raise ValueError("time data did not match format:  data=%s  fmt=%s" %
index 183ec56297767fac9107985d331a690854b2acca..ee24b72fbb78349a2c1e11080addd9f50d897b26 100644 (file)
@@ -417,6 +417,46 @@ class CalculationTests(unittest.TestCase):
         self.failUnless(result.tm_wday == self.time_tuple.tm_wday,
                         "Calculation of day of the week failed;"
                          "%s != %s" % (result.tm_wday, self.time_tuple.tm_wday))
+
+class CacheTests(unittest.TestCase):
+    """Test that caching works properly."""
+
+    def test_time_re_recreation(self):
+        # Make sure cache is recreated when current locale does not match what
+        # cached object was created with.
+        _strptime.strptime("10", "%d")
+        _strptime._locale_cache.locale_time = _strptime.LocaleTime(lang="Ni")
+        original_time_re = id(_strptime._locale_cache)
+        _strptime.strptime("10", "%d")
+        self.failIfEqual(original_time_re, id(_strptime._locale_cache))
+
+    def test_regex_cleanup(self):
+        # Make sure cached regexes are discarded when cache becomes "full".
+        try:
+            del _strptime._regex_cache['%d']
+        except KeyError:
+            pass
+        bogus_key = 0
+        while len(_strptime._regex_cache) <= 5:
+            _strptime._regex_cache[bogus_key] = None
+            bogus_key += 1
+        _strptime.strptime("10", "%d")
+        self.failUnlessEqual(len(_strptime._regex_cache), 1)
+
+    def test_new_localetime(self):
+        # A new LocaleTime instance should be created when a new TimeRE object
+        # is created.
+        _strptime._locale_cache.locale_time = _strptime.LocaleTime(lang="Ni")
+        locale_time_id = id(_strptime._locale_cache.locale_time)
+        locale_time_lang = _strptime._locale_cache.locale_time.lang
+        _strptime.strptime("10", "%d")
+        self.failIfEqual(locale_time_id,
+                         id(_strptime._locale_cache.locale_time))
+        self.failIfEqual(locale_time_lang,
+                         _strptime._locale_cache.locale_time.lang)
+
+
+
 def test_main():
     test_support.run_unittest(
         getlang_Tests,
@@ -426,6 +466,7 @@ def test_main():
         Strptime12AMPMTests,
         JulianTests,
         CalculationTests,
+        CacheTests
     )
 
 
index 45bf3e5cb631d3a5205759acbd8c9f59135c21ab..cc3dcd82ea20b82774708850309cbcd5ed1153e2 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -26,6 +26,10 @@ Library
 
 - Bug #782369:  fix memory leak in array module.
 
+- Caching in _strptime.py has been re-introduced.  This leads to a large
+  performance boost at the cost of being thread-safe from locale changes
+  while executing time.strptime() .
+
 IDLE
 ----