Skip to content

Restore (or beat) Python 2 performance for arithmetic operations on ints that fit into a single word #101291

Description

Activity

  1. added a commit that references this issue on Jan 30, 2023
  2. added a commit that references this issue on Jan 31, 2023
  3. added a commit that references this issue on Mar 22, 2023
  4. added a commit that references this issue on Mar 27, 2023
  5. added a commit that references this issue on Apr 11, 2023
  6. added a commit that references this issue on May 21, 2023
  7. added a commit that references this issue on May 22, 2023
  8. added a commit that references this issue on May 22, 2023
  9. added a commit that references this issue on May 23, 2023
  10. Yhg1s commented on Jul 6, 2023

    @Yhg1s
    Member

    Has there been any progress in documenting the changes made in Python 3.12? (#101292 (comment))

  11. gvanrossum commented on Jul 7, 2023

    @gvanrossum
    Member

    Maybe @markshannon can answer that? AFAICT all the commits linked above are his. I know we had someone who was interested in pursuing this further but she had to bow out.

  12. Yhg1s commented on Jul 20, 2023

    @Yhg1s
    Member

    @markshannon Where are we with documentation for this? If it's not documented, do we need to start working to roll this back? I'm not comfortable with this change in rc1 if it's not documented.

  13. gvanrossum commented on Jul 20, 2023

    @gvanrossum
    Member

    Mark is at EuroPython. If you are there too you can talk to him. We will get it documented.

  14. gvanrossum commented on Jul 21, 2023

    @gvanrossum
    Member

    I did a little research. It looks like there are two key changes. First, struct _longobject (defined in Include/cpython/longintrepr.h but considered an internal implementation detail) has changed. It used to be

    struct _longobject {
        PyObject_VAR_HEAD
        digit ob_digit[1];
    };
    

    I.e., there was an array ob_digit whose length was abs(ob_size), where sign(ob_size) gave the sign of the overall value.

    The new (still internal) representation is as follows:

    typedef struct _PyLongValue {
        uintptr_t lv_tag; /* Number of digits, sign and flags */
        digit ob_digit[1];
    } _PyLongValue;
    
    struct _longobject {
        PyObject_HEAD
        _PyLongValue long_value;
    };
    

    and there are new internal macros to determine the number of digits and the sign, and a bunch of internal macros to handle "compact" values (which fit in 1-2 "digits").

    There are two new public, unstable APIs to support the concept of "compact" values: PyUnstable_Long_IsCompact and PyUnstable_Long_CompactValue. See https://docs.python.org/3.12/c-api/long.html#c.PyUnstable_Long_IsCompact. (In reality these are implemented as macros, and not intended to be part of any ABI.) Everything else that digs through the internals is defined in Include/internal/pycore_long.h, and requires defining Py_BUILD_CORE.

    Details of what the bits in lv_tag mean are intentionally not published -- these are meant to be opaque. Applications that used to dig through ob_digits using ob_size as guidance will break, and have two options: Switch to calling the Python-level APIs int.to_bytes() and int.from_bytes() via PyObject_CallMethod() (see note at https://docs.python.org/3.12/c-api/long.html#c.PyLong_FromString). Or go hard-core, defining Py_BUILD_CORE and importing pycore_long.h. Or, I guess, an intermediate path is to use the new unstable public APIs for dealing with "compact" values and use the slower arbitrary-precision API for non-compact values.

    I think in the What's New in 3.12 we should at least mention the change in the struct (calling out that using ob_size and ob_digits is no longer supported) and the new unstable public APIs (and what they're for). I don't think we need to call out the hard-core option, but maybe a reminder about to_bytes() and from_bytes() would be useful (even though that's been in the docs at least since 3.10).

    @Yhg1s @markshannon What do you think of this? I volunteer to make a PR for what's new 3.12 along the lines of what I wrote above.

  15. added a commit that references this issue on Jul 28, 2023
  16. added a commit that references this issue on Jul 28, 2023
  17. added a commit that references this issue on Jul 31, 2023
  18. gvanrossum commented on Jul 31, 2023

    @gvanrossum
    Member

    @Yhg1s Assuming the changes Mark made to what's new in 3.12 are what you wanted?

  19. Yhg1s commented on Jul 31, 2023

    @Yhg1s
    Member

    Yep, that's adequate.

  20. added a commit that references this issue on Oct 13, 2024
  21. added 2 commits that reference this issue on Oct 13, 2024
  22. added 2 commits that reference this issue on Oct 13, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)performancePerformance or resource usage

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions