8000 MAINT: Remove internal uses of _inspect module by rossbar · Pull Request #16787 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

MAINT: Remove internal uses of _inspect module #16787

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
8000
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Incorporate more comments from review.
  • Loading branch information
rossbar committed Aug 3, 2020
commit c1eeb824f7d927d53abf6aef72f93c05d414e2d2
3 changes: 1 addition & 2 deletions numpy/core/overrides.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def verify_matching_signatures(implementation, dispatcher):
implementation_sig = inspect.signature(implementation)
Copy link
Member

Choose a reason for hiding this comment

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

I can only assume the timings are bad because inspect.signature is slower than getargspec

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, some (very rough) profiling indicates that this is the case. Using the following setup:

from numpy.core.overrides import verify_matching_signatures                     
                                                                                
def foo(                                                                        
    a, b, m, n, k, copy=False, color="red", normed=False, weights=None,         
    bins=10, density=None, size=1024, shape=(3, 4)                              
):                                                                              
    pass                                                                        
                                                                                
def _foo_dispatcher(                                                            
    a, b, m, n, k, copy=None, color=None, normed=None, weights=None,            
    bins=None, density=None, size=None, shape=None                              
):                                                                              
    pass

timeit gives:

On 6e35c2a (this PR):

In [2]: %timeit verify_matching_signatures(foo, _foo_dispatcher)                             
73.1 µs ± 879 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

On 2283e26 (root of branch):

In [2]: %timeit verify_matching_signatures(foo, _foo_dispatcher)                             
4.85 µs ± 11.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

So the implementation based on inspect.signature is about 15x slower than the original based on _inspect.getargspec.

One idea I had was to try to re-implement this with inspect.getfullargspec, which is the more full-featured extension of the original (now deprecated) inspect.getargspec. I will update with -X importtime & profiling info from the attempt.

Copy link
Member
@eric-wieser eric-wieser Aug 28, 2020

Choose a reason for hiding this comment

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

One idea I had was to try to re-implement this with inspect.getfullargspec, which is the more full-featured extension of the original (now deprecated) inspect.getargspec.

This is implemented in terms of inspect.signature, then does some extra processing. You'd do better to probe the __code__ object directly.

Perhaps the comparison is the slow part.

dispatcher_sig = inspect.signature(dispatcher)

implementation_sig_with_none_defaults = implementation_sig.replace(
implementation_sig_with_none_defaults = inspect.Signature(
parameters=[
p.replace(
annotation=inspect.Parameter.empty,
Expand All @@ -83,7 +83,6 @@ def verify_matching_signatures(implementation, dispatcher):
)
for p in implementation_sig.parameters.values()
],
return_annotation=inspect.Signature.empty
)

if dispatcher_sig != implementation_sig_with_none_defaults:
Expand Down
0