add caching to _build_regex_range
- _build_regex_range is called 17 times on import of nova.api.validation.parameters_types. _build_regex_range internally calls re.escape and valid_char on every char returned from _get_all_chars. _get_all_chars yields all chars up to 0xffff. As a result re.escape and valid_char are called 1.1 million times when nova.api.validation.parameters_types is imported. - This change add a memorize decorator and uses it to cache _build_regex_range - This change does not cache valid_char, _is_printable or re.escape as hashing and caching them for each invocation would be far more costly both in time and memory than computing the result. Change-Id: Ic1f2c560a6da815b26fdf770450bbe439d18d4f9 Closes-Bug: #1790195
This commit is contained in:
parent
6522ea3ecf
commit
90b206894a
|
@ -16,6 +16,7 @@ Common parameter types for validating request Body.
|
|||
|
||||
"""
|
||||
import copy
|
||||
import functools
|
||||
import re
|
||||
import unicodedata
|
||||
|
||||
|
@ -24,6 +25,27 @@ import six
|
|||
from nova.i18n import _
|
||||
from nova.objects import tag
|
||||
|
||||
_REGEX_RANGE_CACHE = {}
|
||||
|
||||
|
||||
def memorize(func):
|
||||
|
||||
@functools.wraps(func)
|
||||
def memorizer(*args, **kwargs):
|
||||
global _REGEX_RANGE_CACHE
|
||||
key = "%s:%s:%s" % (func.__name__, hash(str(args)), hash(str(kwargs)))
|
||||
value = _REGEX_RANGE_CACHE.get(key)
|
||||
if value is None:
|
||||
value = func(*args, **kwargs)
|
||||
_REGEX_RANGE_CACHE[key] = value
|
||||
return value
|
||||
return memorizer
|
||||
|
||||
|
||||
def _reset_cache():
|
||||
global _REGEX_RANGE_CACHE
|
||||
_REGEX_RANGE_CACHE = {}
|
||||
|
||||
|
||||
def single_param(schema):
|
||||
"""Macro function for use in JSONSchema to support query parameters that
|
||||
|
@ -83,6 +105,7 @@ def _get_all_chars():
|
|||
# constraint fails and this causes issues for some unittests when
|
||||
# PYTHONHASHSEED is set randomly.
|
||||
|
||||
@memorize
|
||||
def _build_regex_range(ws=True, invert=False, exclude=None):
|
||||
"""Build a range regex for a set of characters in utf8.
|
||||
|
||||
|
|
|
@ -95,7 +95,9 @@ class ValidationRegex(test.NoDBTestCase):
|
|||
self.useFixture(fixtures.MonkeyPatch(
|
||||
'nova.api.validation.parameter_types._get_all_chars',
|
||||
_get_all_chars))
|
||||
|
||||
# note that since we use only the ascii range in the tests
|
||||
# we have to clear the cache to recompute them.
|
||||
parameter_types._reset_cache()
|
||||
r = parameter_types._build_regex_range(ws=False)
|
||||
self.assertEqual(r, re.escape('!') + '-' + re.escape('~'))
|
||||
|
||||
|
|
Loading…
Reference in New Issue