| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
|
||
| # If this is a wrapped function, unwrap it. | ||
| member = inspect.unwrap(member) | ||
| if not isinstance(member, type) and hasattr(member, '__wrapped__'): |
There was a problem hiding this comment.
This check was copied from the while loop in inspect.unwrap
Sorry, something went wrong.
|
Deferring the call to inspect.signature to create __doc__ might also speed up the dataclasses creation a bit. e.g. here's what I see in a cProfile of the _colorize module which uses dataclasses heavily (on main branch) $ ./python -m cProfile -m _colorize | head 20
5604 function calls (5484 primitive calls) in 0.007 seconds
Ordered by: cumulative time
ncalls tottime percall cumtime percall filename:lineno(function)
9/1 0.004 0.000 0.007 0.007 {built-in method builtins.exec}
1 0.000 0.000 0.007 0.007 <string>:1(<module>)
1 0.000 0.000 0.007 0.007 <frozen runpy>:199(run_module)
1 0.000 0.000 0.007 0.007 <frozen runpy>:65(_run_code)
1 0.000 0.000 0.007 0.007 _colorize.py:1(<module>)
7 0.000 0.000 0.006 0.001 dataclasses.py:1432(wrap)
7 0.000 0.000 0.006 0.001 dataclasses.py:986(_process_class)
7 0.000 0.000 0.004 0.001 dataclasses.py:478(add_fns_to_class)
4 0.000 0.000 0.001 0.000 inspect.py:3343(signature)
4 0.000 0.000 0.001 0.000 inspect.py:3056(from_callable)
12/4 0.000 0.000 0.001 0.000 inspect.py:2437(_signature_from_callable)
4 0.000 0.000 0.001 0.000 inspect.py:2331(_signature_from_function)
71/11 0.000 0.000 0.000 0.000 annotationlib.py:907(get_annotations)
8 0.000 0.000 0.000 0.000 dataclasses.py:541(__annotate__)
17/9 0.000 0.000 0.000 0.000 annotationlib.py:1114(_get_and_call_annotate) |
Sorry, something went wrong.
|
I believe we should add a NEWS entry, because it is user-facing change (at least in the performance terms). |
Sorry, something went wrong.
|
As a side effect that may be worth noting, deferring __doc__ generation also 'fixes' the output for self referential dataclasses1. @dataclass
class Example:
examples: list[Example]
print(Example.__doc__)Before: "Example(examples: list[ForwardRef('Example', is_class=True, owner=<class '__main__.Example'>)])"PR: 'Example(examples: list[__main__.Example])'Every dataclass is getting its own _AutoDocString instance, could they share the same instance? Following on from this, the re and copy imports could also potentially be deferred, copy is only used in some cases for the serialization methods and re is only used for string annotations. Deferring re only makes sense if inspect is also deferred as inspect currently eagerly imports it (I see you have a PR to change that too though). Footnotes
|
Sorry, something went wrong.
They could; that would be nice. |
Sorry, something went wrong.
Sorry, something went wrong.
Ideally with the new annotations, uses of __future__ annotations will become less common and so they won't need the import. Modules like _colorize should already benefit as they don't use __future__ annotations. |
Sorry, something went wrong.
|
I'm not sure we should mix changes for _MODULE_IDENTIFIER_RE and __doc__ in one PR. But I'm not an expert here. |
Sorry, something went wrong.
|
@danielhollas If you open a new PR with the lazy imports and global regex I'm happy to merge those. I'd prefer someone else to review the autodoc stuff. |
Sorry, something went wrong.
|
@hugovk worth noting as it was one of the driving forces behind this that you lose a chunk of the benefit in _colorize without the autodoc stuff unless you write docstrings for the remaining dataclasses without them. The lack of docstring will trigger the inspect import. One way of encouraging people to document their classes I guess 🙂 . |
Sorry, something went wrong.
Thanks, I could do, but note that deferring re without deferring inspect is pointless since inspect imports re as well. (and it also wouldn't help _colorize since re is imported there as well). If you think splitting these two changes would help with the review I'll do it, but I think a more impactful thing here would be to tag somebody who you think should review this. |
Sorry, something went wrong.
I was wrong, I forgot that I made re lazy in inspect recently in #144756 😅 I've split the re and copy lazy imports in #148379. I will rebase this PR once that one is merged. |
Sorry, something went wrong.
|
Alright, #148379 has been merged (thanks Hugo!) so this PR is now only about lazy importing inspect module. |
Sorry, something went wrong.
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
|
Hi all, just a note that I will be away for two weeks starting 1st of May. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
inspect module is slow to import (see #117865) and is dragging down dataclasses with it.
There are currently only two uses of inspect in dataclasses, but they are a bit tricky to inline since they are on a direct code path when the @dataclass decorator is executed.
For 1. I have used a descriptor protocol to generate the __doc__ attribute on demand (this is my first time messing with descriptors, apologies if I overlooked something).
For 2. can be deferred by calling the unwrap functions only when really necessary (and hopefully this path is not common)
Benchmarks
./python -Ximporttime -c "import dataclasses"Before
After
Overall seems to be a solid 20-30% improvement.