Skip to content

Commit 738506c

Browse files
authored
Fix performance regression in sentry_sdk.utils._generate_installed_modules (#2703)
Commit 8c24d33 causes a performance regression when PYTHONPATH is long, because it traverses PYTHONPATH for every distribution found (importlib.metadata.version traverses PYTHONPATH searching for a matching distribution for every call) In our case we have an environment containing ~500 paths, and containing ~100 distributions, and where the first call to sentry_sdk.utils.package_version causes ~150k filesystems operations taking 10-20 seconds. This commit uses the version from the distribution found when iterating all distributions, instead of calling importlib.metadata.version for each, which fixes the performance issue for us. Note that if multiple copies of a distribution with different versions exist in PYTHONPATH the existing _generate_installed_modules will return the name and version of the first matching distribution found multiple times, which will then be discarded by creation of a dict in _get_installed_modules. I have preserved the same behaviour by returning the name and version of a distribution only the first time a distribution name is seen.
1 parent 4afb955 commit 738506c

File tree

1 file changed

+5
-3
lines changed

1 file changed

+5
-3
lines changed

sentry_sdk/utils.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,16 +1666,18 @@ def _generate_installed_modules():
16661666
try:
16671667
from importlib import metadata
16681668

1669+
yielded = set()
16691670
for dist in metadata.distributions():
16701671
name = dist.metadata["Name"]
16711672
# `metadata` values may be `None`, see:
16721673
# https://github.com/python/cpython/issues/91216
16731674
# and
16741675
# https://github.com/python/importlib_metadata/issues/371
16751676
if name is not None:
1676-
version = metadata.version(name)
1677-
if version is not None:
1678-
yield _normalize_module_name(name), version
1677+
normalized_name = _normalize_module_name(name)
1678+
if dist.version is not None and normalized_name not in yielded:
1679+
yield normalized_name, dist.version
1680+
yielded.add(normalized_name)
16791681

16801682
except ImportError:
16811683
# < py3.8

0 commit comments

Comments
 (0)