config: avoid stat storm in _getconftestmodules

Fix #9478.
This commit is contained in:
Ran Benita 2022-01-22 00:27:43 +02:00
parent bb5a4e2d63
commit aee04cd49f
1 changed files with 14 additions and 4 deletions

View File

@ -330,6 +330,14 @@ def _prepareconfig(
raise raise
def _get_directory(path: Path) -> Path:
"""Get the directory of a path - itself if already a directory."""
if path.is_file():
return path.parent
else:
return path
@final @final
class PytestPluginManager(PluginManager): class PytestPluginManager(PluginManager):
"""A :py:class:`pluggy.PluginManager <pluggy.PluginManager>` with """A :py:class:`pluggy.PluginManager <pluggy.PluginManager>` with
@ -357,6 +365,11 @@ class PytestPluginManager(PluginManager):
# If set, conftest loading is skipped. # If set, conftest loading is skipped.
self._noconftest = False self._noconftest = False
# _getconftestmodules()'s call to _get_directory() causes a stat
# storm when it's called potentially thousands of times in a test
# session (#9478), often with the same path, so cache it.
self._get_directory = lru_cache(256)(_get_directory)
self._duplicatepaths: Set[Path] = set() self._duplicatepaths: Set[Path] = set()
# plugins that were explicitly skipped with pytest.skip # plugins that were explicitly skipped with pytest.skip
@ -547,10 +560,7 @@ class PytestPluginManager(PluginManager):
if self._noconftest: if self._noconftest:
return [] return []
if path.is_file(): directory = self._get_directory(path)
directory = path.parent
else:
directory = path
# Optimization: avoid repeated searches in the same directory. # Optimization: avoid repeated searches in the same directory.
# Assumes always called with same importmode and rootpath. # Assumes always called with same importmode and rootpath.