https://github.com/python/cpython/commit/65ed1b742985ea615d47988fda72090b177f0b45
commit: 65ed1b742985ea615d47988fda72090b177f0b45
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: brettcannon <[email protected]>
date: 2024-07-03T21:14:42Z
summary:

[3.13] gh-117983: Defer import of threading for lazy module loading (GH-120233) 
(GH-121349)

gh-117983: Defer import of threading for lazy module loading (GH-120233)

As noted in gh-117983, the import importlib.util can be triggered at
interpreter startup under some circumstances, so adding threading makes
it a potentially obligatory load.
Lazy loading is not used in the stdlib, so this removes an unnecessary
load for the majority of users and slightly increases the cost of the
first lazily loaded module.

An obligatory threading load breaks gevent, which monkeypatches the
stdlib. Although unsupported, there doesn't seem to be an offsetting
benefit to breaking their use case.

For reference, here are benchmarks for the current main branch:

```
❯ hyperfine -w 8 './python -c "import importlib.util"'
Benchmark 1: ./python -c "import importlib.util"
  Time (mean ± σ):       9.7 ms ±   0.7 ms    [User: 7.7 ms, System: 1.8 ms]
  Range (min … max):     8.4 ms …  13.1 ms    313 runs
```

And with this patch:

```
❯ hyperfine -w 8 './python -c "import importlib.util"'
Benchmark 1: ./python -c "import importlib.util"
  Time (mean ± σ):       8.4 ms ±   0.7 ms    [User: 6.8 ms, System: 1.4 ms]
  Range (min … max):     7.2 ms …  11.7 ms    352 runs
```

Compare to:

```
❯ hyperfine -w 8 './python -c pass'
Benchmark 1: ./python -c pass
  Time (mean ± σ):       7.6 ms ±   0.6 ms    [User: 5.9 ms, System: 1.6 ms]
  Range (min … max):     6.7 ms …  11.3 ms    390 runs
```

This roughly halves the import time of importlib.util.
(cherry picked from commit 94f50f8ee6872007d46c385f7af253497273255a)

Co-authored-by: Chris Markiewicz <[email protected]>

files:
A Misc/NEWS.d/next/Library/2024-06-07-10-10-32.gh-issue-117983.NeMR9n.rst
M Lib/importlib/util.py

diff --git a/Lib/importlib/util.py b/Lib/importlib/util.py
index c94a148e4c50e0..284206b62f9409 100644
--- a/Lib/importlib/util.py
+++ b/Lib/importlib/util.py
@@ -13,7 +13,6 @@
 
 import _imp
 import sys
-import threading
 import types
 
 
@@ -257,6 +256,9 @@ def create_module(self, spec):
 
     def exec_module(self, module):
         """Make the module load lazily."""
+        # Threading is only needed for lazy loading, and importlib.util can
+        # be pulled in at interpreter startup, so defer until needed.
+        import threading
         module.__spec__.loader = self.loader
         module.__loader__ = self.loader
         # Don't need to worry about deep-copying as trying to set an attribute
diff --git 
a/Misc/NEWS.d/next/Library/2024-06-07-10-10-32.gh-issue-117983.NeMR9n.rst 
b/Misc/NEWS.d/next/Library/2024-06-07-10-10-32.gh-issue-117983.NeMR9n.rst
new file mode 100644
index 00000000000000..cca97f50a20496
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-06-07-10-10-32.gh-issue-117983.NeMR9n.rst
@@ -0,0 +1,2 @@
+Defer the ``threading`` import in ``importlib.util`` until lazy loading is
+used.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to