Skip to content

Commit

Permalink
perf: cache requires-python checks & skip debug logging (#13128)
Browse files Browse the repository at this point in the history
The requires-python check is pretty fast, but when performed for
10000 links, the checks consume a nontrivial amount of time. For
example, while installing (pre-cached + --dry-run) a pared down list of
homeassistant dependencies (n=117), link evaluation took 15% of the
total runtime, with requires-python evaluation accounting for half
(7.5%) of that.

The cache can be kept pretty small as requires-python specifiers often
repeat, and when they do change, it's often in chunks (or between
entirely different packages). For example, setuptools has like 1500
links, but only ~12 different `requires-python` specifiers.

In addition, _log_skipped_link() is a hot method and unfortunately
expensive as it hashes the link on every call. Fortunately, we can
return early when debug logging is not enabled. In the same
homeassistant run, this saves 0.7% of the runtime.
  • Loading branch information
ichard26 authored Jan 12, 2025
1 parent 4ad7295 commit a84a940
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 0 deletions.
1 change: 1 addition & 0 deletions news/13128.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Cache ``python-requires`` checks while filtering potential installation candidates.
5 changes: 5 additions & 0 deletions src/pip/_internal/index/package_finder.py
Original file line number Diff line number Diff line change
Expand Up @@ -736,6 +736,11 @@ def _sort_links(self, links: Iterable[Link]) -> List[Link]:
return no_eggs + eggs

def _log_skipped_link(self, link: Link, result: LinkType, detail: str) -> None:
# This is a hot method so don't waste time hashing links unless we're
# actually going to log 'em.
if not logger.isEnabledFor(logging.DEBUG):
return

entry = (link, result, detail)
if entry not in self._logged_links:
# Put the link at the end so the reason is more visible and because
Expand Down
1 change: 1 addition & 0 deletions src/pip/_internal/utils/packaging.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
logger = logging.getLogger(__name__)


@functools.lru_cache(maxsize=32)
def check_requires_python(
requires_python: Optional[str], version_info: Tuple[int, ...]
) -> bool:
Expand Down

0 comments on commit a84a940

Please sign in to comment.