Skip to content

Commit 5c69476

Browse files
gh-96346: Use double caching for re._compile()
1 parent 6fbd889 commit 5c69476

File tree

2 files changed

+36
-19
lines changed

2 files changed

+36
-19
lines changed

Lib/re/__init__.py

+35-19
Original file line numberDiff line numberDiff line change
@@ -267,39 +267,55 @@ def escape(pattern):
267267
# internals
268268

269269
_cache = {} # ordered!
270+
_cache2 = {} # ordered!
270271

271272
_MAXCACHE = 512
273+
_MAXCACHE2 = 256
272274
def _compile(pattern, flags):
273275
# internal: compile pattern
274276
if isinstance(flags, RegexFlag):
275277
flags = flags.value
276278
try:
277-
return _cache[type(pattern), pattern, flags]
279+
return _cache2[type(pattern), pattern, flags]
278280
except KeyError:
279281
pass
280-
if isinstance(pattern, Pattern):
281-
if flags:
282-
raise ValueError(
283-
"cannot process flags argument with a compiled pattern")
284-
return pattern
285-
if not _compiler.isstring(pattern):
286-
raise TypeError("first argument must be string or compiled pattern")
287-
if flags & T:
288-
import warnings
289-
warnings.warn("The re.TEMPLATE/re.T flag is deprecated "
290-
"as it is an undocumented flag "
291-
"without an obvious purpose. "
292-
"Don't use it.",
293-
DeprecationWarning)
294-
p = _compiler.compile(pattern, flags)
295-
if not (flags & DEBUG):
282+
283+
key = (type(pattern), pattern, flags)
284+
p = _cache.pop(key, None)
285+
if p is None:
286+
if isinstance(pattern, Pattern):
287+
if flags:
288+
raise ValueError(
289+
"cannot process flags argument with a compiled pattern")
290+
return pattern
291+
if not _compiler.isstring(pattern):
292+
raise TypeError("first argument must be string or compiled pattern")
293+
if flags & T:
294+
import warnings
295+
warnings.warn("The re.TEMPLATE/re.T flag is deprecated "
296+
"as it is an undocumented flag "
297+
"without an obvious purpose. "
298+
"Don't use it.",
299+
DeprecationWarning)
300+
p = _compiler.compile(pattern, flags)
301+
if flags & DEBUG:
302+
return p
296303
if len(_cache) >= _MAXCACHE:
297-
# Drop the oldest item
304+
# Drop the least used item
298305
try:
299306
del _cache[next(iter(_cache))]
300307
except (StopIteration, RuntimeError, KeyError):
301308
pass
302-
_cache[type(pattern), pattern, flags] = p
309+
# Append to the end
310+
_cache[key] = p
311+
312+
if len(_cache2) >= _MAXCACHE2:
313+
# Drop the oldest item
314+
try:
315+
del _cache2[next(iter(_cache2))]
316+
except (StopIteration, RuntimeError, KeyError):
317+
pass
318+
_cache2[key] = p
303319
return p
304320

305321
@functools.lru_cache(_MAXCACHE)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Use double caching for compiled RE patterns.

0 commit comments

Comments
 (0)