Skip to content
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

bpo-42202: Store func annotations as single tuple at bytecode level #23316

Merged
merged 33 commits into from
Nov 25, 2020

Conversation

uriyyo
Copy link
Member

@uriyyo uriyyo commented Nov 16, 2020

Store func annotations as single tuple at bytecode level.

https://bugs.python.org/issue42202

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

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

LGTM in general.

Objects/codeobject.c Outdated Show resolved Hide resolved
Objects/codeobject.c Outdated Show resolved Hide resolved
Objects/funcobject.c Outdated Show resolved Hide resolved
Python/compile.c Outdated Show resolved Hide resolved
Python/compile.c Outdated Show resolved Hide resolved
Python/compile.c Outdated Show resolved Hide resolved
Python/compile.c Outdated Show resolved Hide resolved
PC/launcher.c Outdated Show resolved Hide resolved
Include/cpython/code.h Outdated Show resolved Hide resolved
@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@uriyyo uriyyo requested review from serhiy-storchaka and removed request for a team November 16, 2020 22:25
@uriyyo
Copy link
Member Author

uriyyo commented Nov 17, 2020

@serhiy-storchaka I have implemented the same logic for module and class annotations, so all annotations will be computed at compilation time.

@uriyyo uriyyo force-pushed the fix-issue-42202 branch 3 times, most recently from a4d717f to d1f7312 Compare November 17, 2020 15:38
Lib/test/test_opcodes.py Outdated Show resolved Hide resolved
@uriyyo
Copy link
Member Author

uriyyo commented Nov 17, 2020

I have made the requested changes; please review again

@bedevere-bot
Copy link

Thanks for making the requested changes!

@serhiy-storchaka: please review the changes made to this pull request.

@markshannon
Copy link
Member

Rather than return the tuple size via a pointer (out) parameter, you can return the size directly as it cannot be negative, leaving -1 to signify an error. So,

int compiler_visit_argannotation(struct compiler *c, identifier id, expr_ty annotation, Py_ssize_t *annotations_len);

becomes

int compiler_visit_argannotation(struct compiler *c, identifier id, expr_ty annotation);

and the use changes from

if (compiler_visit_argannotation(..., &len))
    goto error;

to

len = compiler_visit_argannotation(...);
if (len < 0)
    goto error;

@uriyyo
Copy link
Member Author

uriyyo commented Nov 24, 2020

Rather than return the tuple size via a pointer (out) parameter, you can return the size directly as it cannot be negative,
leaving -1 to signify an error.

I think it will make code more complicated because it will require rewriting all ifs for compiler_visit_annotations function.

It will be great if compiler_visit_argannotations and compiler_visit_argannotation will follow the same conventions - return tuple size through the pointer or as return value.

@markshannon What is your opinion regarding that?

@markshannon
Copy link
Member

I prefer my approach (I wouldn't have suggested it otherwise 🙂 ), but the code is fine as it is.

I'm still happy with merging it.

@uriyyo
Copy link
Member Author

uriyyo commented Nov 24, 2020

I totally agree with you, personally, I don't like when the return value passed through the pointer instead of simple return, as zen said explicit is better than implicit.

But otherwise, In my opinion, it will make code less readable.
From this:

if (!compiler_visit_argannotations(c, args->args, &annotations_len))
   return 0;
if (args->vararg && args->vararg->annotation &&
    !compiler_visit_argannotation(c, args->vararg->arg,
                                  args->vararg->annotation, &annotations_len))
   return 0;

It will be rewritten to:

    len = compiler_visit_argannotations(c, args->args);
    if (len < 0)
        return 0;
    annotations_len += len;
    if (args->vararg && args->vararg->annotation) {
        len = compiler_visit_argannotation(c, args->vararg->arg,
                                           args->vararg->annotation);
        if (len < 0)
            return 0;
        annotations_len += len;
    }

This situation is a double-edged sword when we should choose between code readability and code explicity.

Copy link
Member

@Fidget-Spinner Fidget-Spinner left a comment

Choose a reason for hiding this comment

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

I don't have anything valuable to add here, just a small nitpick with the whatsnew.

This optimization makes me really happy :). Thanks Yuri for the PR and Inada-san for the concept.

Doc/whatsnew/3.10.rst Outdated Show resolved Hide resolved
Co-authored-by: kj <28750310+Fidget-Spinner@users.noreply.github.com>
@uriyyo
Copy link
Member Author

uriyyo commented Nov 24, 2020

@Fidget-Spinner Thank you for making docs more clear and for adding Inada to the list of contributors. It's my bad, I must definitely add Inada to the contributor's list because this PR is fully his idea.

@uriyyo
Copy link
Member Author

uriyyo commented Nov 24, 2020

Can someone rerun Azure Pipelines?
I believe it failed not because of my code)

@methane methane closed this Nov 25, 2020
@methane methane reopened this Nov 25, 2020
@methane
Copy link
Member

methane commented Nov 25, 2020

Even core committers can not re-run Azure Pipeline. Close and reopen is the most easy way to rebuild, although it starts not only Azure Pipeline.

@uriyyo
Copy link
Member Author

uriyyo commented Nov 25, 2020

@methane Looks like everything is done and this PR can be merged

@methane
Copy link
Member

methane commented Nov 25, 2020

I did make regen-importlib but I could not git push to your repository. Would you do it?

@uriyyo
Copy link
Member Author

uriyyo commented Nov 25, 2020

I did make regen-importlib but I could not git push to your repository. Would you do it?

Sure, no problems.

@uriyyo
Copy link
Member Author

uriyyo commented Nov 25, 2020

@methane I have regenerated import-lib

@methane methane merged commit 7301979 into python:master Nov 25, 2020
@methane
Copy link
Member

methane commented Nov 25, 2020

Congrats, @uriyyo. And thank you reviewers.

@uriyyo
Copy link
Member Author

uriyyo commented Nov 25, 2020

Thanks all, I am happy that we merge this PR💫

@methane Should we do smth similar for class/module annotations?

adorilson pushed a commit to adorilson/cpython that referenced this pull request Mar 13, 2021
Reduce memory footprint and improve performance of loading modules having many func annotations.

  >>> sys.getsizeof({"a":"int","b":"int","return":"int"})
  232
  >>> sys.getsizeof(("a","int","b","int","return","int"))
  88

The tuple is converted into dict on the fly when `func.__annotations__` is accessed first.

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Co-authored-by: Inada Naoki <songofacandy@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants