twister: Fix quarantine performance issue

When using a quarantine file with more than 512 unique
entries, than time of matching quarantine increases
significantly. This is because regexp cache size is
512. Add precompiled regexp entries to the quarantine
as a fix.

Signed-off-by: Grzegorz Chwierut <grzegorz.chwierut@nordicsemi.no>
This commit is contained in:
Grzegorz Chwierut 2023-09-29 10:48:50 +02:00 committed by Fabio Baltieri
commit fd6f3c5a2a
2 changed files with 18 additions and 9 deletions

View file

@ -41,6 +41,10 @@ class QuarantineElement:
architectures: list[str] = field(default_factory=list)
simulations: list[str] = field(default_factory=list)
comment: str = 'NA'
re_scenarios: list = field(default_factory=list)
re_platforms: list = field(default_factory=list)
re_architectures: list = field(default_factory=list)
re_simulations: list = field(default_factory=list)
def __post_init__(self):
# If there is no entry in filters then take all possible values.
@ -53,6 +57,12 @@ class QuarantineElement:
self.architectures = []
if 'all' in self.simulations:
self.simulations = []
# keep precompiled regexp entiries to speed-up matching
self.re_scenarios = [re.compile(pat) for pat in self.scenarios]
self.re_platforms = [re.compile(pat) for pat in self.platforms]
self.re_architectures = [re.compile(pat) for pat in self.architectures]
self.re_simulations = [re.compile(pat) for pat in self.simulations]
# However, at least one of the filters ('scenarios', platforms' ...)
# must be given (there is no sense to put all possible configuration
# into quarantine)
@ -101,16 +111,16 @@ class QuarantineData:
for qelem in self.qlist:
matched: bool = False
if (qelem.scenarios
and (matched := _is_element_matched(scenario, qelem.scenarios)) is False):
and (matched := _is_element_matched(scenario, qelem.re_scenarios)) is False):
continue
if (qelem.platforms
and (matched := _is_element_matched(platform, qelem.platforms)) is False):
and (matched := _is_element_matched(platform, qelem.re_platforms)) is False):
continue
if (qelem.architectures
and (matched := _is_element_matched(architecture, qelem.architectures)) is False):
and (matched := _is_element_matched(architecture, qelem.re_architectures)) is False):
continue
if (qelem.simulations
and (matched := _is_element_matched(simulation, qelem.simulations)) is False):
and (matched := _is_element_matched(simulation, qelem.re_simulations)) is False):
continue
if matched:
@ -118,9 +128,9 @@ class QuarantineData:
return None
def _is_element_matched(element: str, list_of_elements: list) -> bool:
def _is_element_matched(element: str, list_of_elements: list[re.Pattern]) -> bool:
"""Return True if given element is matching to any of elements from the list"""
for pattern in list_of_elements:
if re.fullmatch(pattern, element):
if pattern.fullmatch(element):
return True
return False

View file

@ -104,10 +104,9 @@ def test_quarantinedata_post_init():
quarantine_element = QuarantineElement(
platforms=['dummy platform'],
architectures=[]
architectures=[],
simulations=['dummy simulation', 'another simulation']
)
quarantine_element.scenarios = []
quarantine_element.simulations = ['dummy simulation', 'another simulation']
quarantine_data_qlist = [quarantine_element, quarantine_element_dict]