You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#852 introduced a large regression in terms of startup overhead:
❯ docker run --rm -it python:3.13 bash
root@fe224bc3d8c0:/# pip install -qqq msgspec
root@fe224bc3d8c0:/# python -m timeit -n 1 -r 1 "import msgspec"
1 loop, best of 1: 11.7 msec per loop
root@fe224bc3d8c0:/# python -m timeit -n 1 -r 1 "import inspect"
1 loop, best of 1: 7.84 msec per loop
It's worth noting that as of 3.14 the inspect.get_annotations function moved to annotationlib (which the C code in that PR imports directly) and inspect merely re-exports it. That module loads twice as fast but ideally we wouldn't incur any unnecessary overhead:
❯ docker run --rm -it python:3.14 bash
root@8130942e2641:/# python -m timeit -n 1 -r 1 "import annotationlib"
1 loop, best of 1: 3.34 msec per loop
We need to investigate if removing that import is feasible in terms of what duplicates of logic would have to be maintained here.
I submitted #882 that mitigates this, especially on older versions. It still imports annotationlib on 3.14 though. If you really want to avoid that import too, it is perhaps possible to inline the logic—though in that case it might make more sense to first focus on removing the eager import of typing, a much bigger module than annotationlib.
We need annotationlib.get_annotations on 3.14 primarily to avoid the class of issues discussed in https://peps.python.org/pep-0749/#annotations-and-metaclasses , which means that accessing cls.__annotations__ is not always safe. The implementation that is now in CPython mostly mitigates this (so that using cls.__annotations__ is usually safe), except in certain cases involving from __future__ import annotations. Usually is not always, so it's more correct to keep using annotationlib.get_annotations.
The C code also imports annotationlib where needed. Replacing that would require inlining the logic it uses (get_annotate_from_class_namespace); that would be somewhat tedious to do in C and make the implementation less stable, increasing the chance it will have to change in a future version of Python.
I merged that improvement, thanks! You've definitely sold me on permanently keeping annotationlib.
I'm still learning the codebase but isn't it impossible to remove typing imports since the runtime behavior (I think) depends directly on certain types that module exposes?
It's definitely difficult but maybe the imports can be made lazily. For example, there is a check if something is typing.Required; maybe you can import typing only if the thing is an object with __module__ == "typing". It's likely complicated, and it might make runtime performance worse, but if you really want to minimize import time, it might be worth it.
Activity
JelleZijlstra commentedon Oct 19, 2025
I submitted #882 that mitigates this, especially on older versions. It still imports annotationlib on 3.14 though. If you really want to avoid that import too, it is perhaps possible to inline the logic—though in that case it might make more sense to first focus on removing the eager import of
typing, a much bigger module than annotationlib.We need
annotationlib.get_annotationson 3.14 primarily to avoid the class of issues discussed in https://peps.python.org/pep-0749/#annotations-and-metaclasses , which means that accessingcls.__annotations__is not always safe. The implementation that is now in CPython mostly mitigates this (so that usingcls.__annotations__is usually safe), except in certain cases involvingfrom __future__ import annotations. Usually is not always, so it's more correct to keep usingannotationlib.get_annotations.The C code also imports
annotationlibwhere needed. Replacing that would require inlining the logic it uses (get_annotate_from_class_namespace); that would be somewhat tedious to do in C and make the implementation less stable, increasing the chance it will have to change in a future version of Python.ofek commentedon Oct 19, 2025
I merged that improvement, thanks! You've definitely sold me on permanently keeping
annotationlib.I'm still learning the codebase but isn't it impossible to remove
typingimports since the runtime behavior (I think) depends directly on certain types that module exposes?JelleZijlstra commentedon Oct 19, 2025
It's definitely difficult but maybe the imports can be made lazily. For example, there is a check if something
is typing.Required; maybe you can import typing only if the thing is an object with__module__ == "typing". It's likely complicated, and it might make runtime performance worse, but if you really want to minimize import time, it might be worth it.ofek commentedon Oct 20, 2025
I split further work here into 2 issues:
annotationlib#883