Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-109653: Improve the import time ofemail.utils#109824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
hauntsaninja merged 12 commits intopython:mainfromAlexWaygood:email-message-import
Oct 12, 2023

Conversation

AlexWaygood
Copy link
Member

@AlexWaygoodAlexWaygood commentedSep 25, 2023
edited by bedevere-appbot
Loading

This patch reduces the import time ofemail.utils by around 46%.

Why do I care aboutemail.utils? Well,email.utils is imported byemail.message, andemail.message is imported by lots of other stdlib modules:urllib.parse,mailbox, andimportlib.metadata. Improving the import time of this module has a cascading effect through lots of the rest of the standard library.

A lot of the import cost ofemail.utils has to do with themake_msgid function, which requires therandom andsocket modules. This function is used by many third-party libraries, but isn't used at all by any of the stdlib modules that importemail.utils. This patch moves the function into a separate submodule.

@AlexWaygoodAlexWaygood added type-featureA feature request or enhancement performancePerformance or resource usage topic-email 3.13bugs and security fixes labelsSep 25, 2023
@AlexWaygoodAlexWaygood requested a review froma team as acode ownerSeptember 25, 2023 10:03
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
if attr == "make_msgid":
from email._msgid import make_msgid
return make_msgid
raise AttributeError(f"module {__name__!r} has no attribute {attr!r}")
Copy link
Member

Choose a reason for hiding this comment

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

In general I don't like performance hacks like this, but they do have their place. I can't speak to whether or not this is a worthwhile performance hack, you should seek approval from the maintainers of the impacted modules for that.

That said, the stdlib itself makes no use of make_msgid, and email.utils is not itself considered part of the new email API. Moving it into a separate module and making that part of the non-legacy public API of the email module would actually make some sense. I guess we'd just call it 'msgid'? Then this code should issue a deprecation warning pointing to the new way to import make_msgid. It feels kind of weird to have a module with just one function, but there isn't really anything else related to it that I can think of. (I wonder...maybe make_msgid actually belongs in the UUID module? Probably not. Wrong RFC.)

@hauntsaninja
Copy link
Contributor

This feels a little strange to me. Should we instead just defer the imports? Might even be faster to do so

@AlexWaygood
Copy link
MemberAuthor

AlexWaygood commentedOct 3, 2023
edited
Loading

This feels a little strange to me. Should we instead just defer the imports? Might even be faster to do so

Yeah, that might be a better shout. Have been meaning to give it a go — just haven't got round to it yet :)

I'm not really enthused about the idea of a painful deprecation period in order to change the place where people are "meant" to import it from. This function is pretty widely used by third-party packages, and the improvement in import time doesn't seem worth the disruption to me :)

@AlexWaygood
Copy link
MemberAuthor

I've updated the PR. I abandoned the idea of adding a new submodule; now I just defer the problematicrandom,socket andos imports to insidemake_msgid(). The reason I didn't do that originally was because I was concerned it would slow down themake_msgid() function, but local experimentation doesn't show that. (I ranpython -m timeit -s "from email.utils import make_msgid" "make_msgid()" both with and without the change to test.) Shows the importance of benchmarking!

AA-Turner reacted with thumbs up emoji

Co-authored-by: Adam Turner <9087854+AA-Turner@users.noreply.github.com>
Copy link
Contributor

@hauntsaninjahauntsaninja left a comment

Choose a reason for hiding this comment

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

Looks good

@@ -94,6 +88,8 @@ def formataddr(pair, charset='utf-8'):
name.encode('ascii')
except UnicodeEncodeError:
if isinstance(charset, str):
# lazy import to improve module import time
from email.charset import Charset
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure I like this one, only fine with it sinceformataddr doesn't look too widely used (a lot of the time it's nice to pay these costs upfront, predictable performance is important, e.g. don't want the first request your webserver serves to be randomly slow)

AlexWaygood reacted with thumbs up emoji
Copy link
MemberAuthor

Choose a reason for hiding this comment

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

(a lot of the time it's nice to pay these costs upfront, predictable performance is important

agreed. On the other hand, though, theemail package goes in quite heavily for lazy imports in some other places, so this does seem in keeping with that general philosophy:

# Some convenience routines. Don't import Parser and Message as side-effects
# of importing email since those cascadingly import most of the rest of the
# email package.
defmessage_from_string(s,*args,**kws):
"""Parse a string into a Message object model.
Optional _class and strict are passed to the Parser constructor.
"""
fromemail.parserimportParser
returnParser(*args,**kws).parsestr(s)
defmessage_from_bytes(s,*args,**kws):
"""Parse a bytes string into a Message object model.
Optional _class and strict are passed to the Parser constructor.
"""
fromemail.parserimportBytesParser
returnBytesParser(*args,**kws).parsebytes(s)
defmessage_from_file(fp,*args,**kws):
"""Read a file and parse its contents into a Message object model.
Optional _class and strict are passed to the Parser constructor.
"""
fromemail.parserimportParser
returnParser(*args,**kws).parse(fp)
defmessage_from_binary_file(fp,*args,**kws):
"""Read a binary file and parse its contents into a Message object model.
Optional _class and strict are passed to the Parser constructor.
"""
fromemail.parserimportBytesParser
returnBytesParser(*args,**kws).parse(fp)

Copy link
MemberAuthor

Choose a reason for hiding this comment

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

I'd be happy to change it so it's imported at the top of the function if you think that'd be better?

Copy link
Contributor

Choose a reason for hiding this comment

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

Nah that'd be worse, module level or here. I'm fine with this as is!

AlexWaygood reacted with thumbs up emoji
@hauntsaninjahauntsaninja merged commitaa3f419 intopython:mainOct 12, 2023
@AlexWaygoodAlexWaygood deleted the email-message-import branchOctober 12, 2023 22:26
@AlexWaygoodAlexWaygood restored the email-message-import branchFebruary 22, 2024 16:37
@AlexWaygoodAlexWaygood deleted the email-message-import branchMarch 7, 2024 14:35
Glyphack pushed a commit to Glyphack/cpython that referenced this pull requestSep 2, 2024
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@bitdancerbitdancerbitdancer left review comments

@sobolevnsobolevnsobolevn left review comments

@AA-TurnerAA-TurnerAA-Turner left review comments

@hauntsaninjahauntsaninjahauntsaninja approved these changes

Assignees
No one assigned
Labels
3.13bugs and security fixesperformancePerformance or resource usagetopic-emailtype-featureA feature request or enhancement
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

5 participants
@AlexWaygood@hauntsaninja@bitdancer@sobolevn@AA-Turner

[8]ページ先頭

©2009-2025 Movatter.jp