Skip to content

Conversation

@notatallshaw
Copy link
Member

@notatallshaw notatallshaw commented Nov 23, 2025

When doing a lot of comparisons with the Specifier class, a lot of redundant temporary Version objects are created for comparison.

This is particularly problematic for pip, which has to call comparisons many times, on one of my resolver benchmark, with #985 already applied, adding the _public_version function reduces the number of times Version is instantiated from ~1.3 million times to ~580k times, and the _base_version function reduces that to ~574k times (_base_version is called in significantly more edge case situations).

return version


def _public_version(version: Version) -> Version:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like this would be cleaner if it was part of version; .local_version could return self if there is no local version, for example; it's a bit of an issue that these returned strings requiring reparsing. But unfortunately, .base_version already has the word "version" in it but returns a string, so not sure there's an obvious way forward with naming if we went that route.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Designing a new API for Version objects to return Version objects doesn't need to block this performance improvement though. We can migrate this to new API once that lands.

I am working on a .replace() method, and I hadn't thought about it, but I can efficiently return self when nothing is modified. That could be the target API.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not blocking, already approved. :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Actually, I approved #986, which I felt was sort of a prerequisite, but I guess it isn't.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the two PRs are technically independent of each other, they just touch some of the exact same lines, I will need to resolve conflicts once one or the other merges, no issue though, I already know the target state.

@notatallshaw notatallshaw merged commit f0f726d into pypa:main Nov 25, 2025
40 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants