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

METH_METHOD calling convention is now not so efficient #123500

Open
neonene opened this issue Aug 30, 2024 · 1 comment
Open

METH_METHOD calling convention is now not so efficient #123500

neonene opened this issue Aug 30, 2024 · 1 comment
Labels
topic-C-API type-bug An unexpected behavior, bug, or error

Comments

@neonene
Copy link
Contributor

neonene commented Aug 30, 2024

Bug report

Bug description:

There are callables implemented with the METH_METHOD|METH_FASTCALL signature in C. They can be 5%-15% less efficient than using only METH_FASTCALL (or METH_O) with a PyType_GetModuleByDef function call.

For example, I measured the difference on Windows PGO builds by duplicating functions:

  • CDataType_from_buffer_copy() in _ctypes.c, which is not called when profiling:

    from timeit import timeit
    setup = """if 1:
        import ctypes
        buf = bytearray(16)
        cls = ctypes.c_char * len(buf)
    """
    # with a warmup
    for _ in range(2):
        # METH_METHOD|METH_FASTCALL (as-is)
        r0 = timeit(s0 := f'cls.from_buffer_copy (buf)', setup)
    
        # METH_FASTCALL (no `defining_class`) + PyType_GetModuleByDef
        r1 = timeit(s1 := f'cls.from_buffer_copy1(buf)', setup)
    
    print(s0, r0, 1 + (1 - r0 / r0))
    print(s1, r1, 1 + (1 - r1 / r0))
    cls.from_buffer_copy (buf) 0.15552800190635024 1.0
    cls.from_buffer_copy1(buf) 0.13187471489945893 1.1520837837364741
  • dec_mpd_qquantize() in _decimal.c profiled with 6800 calls (unfair?):

    # legacy (as-is)
    d1.quantize (d2) 0.1694609627971658 1.0
    
    # METH_METHOD|METH_FASTCALL (`defining_class`) + _PyType_GetModuleState
    d1.quantize1(d2) 0.1408861404022900 1.168621857938327
    
    # METH_FASTCALL (no `defining_class`) + PyType_GetModuleByDef
    d1.quantize2(d2) 0.1258157708973158 1.257553074049807
    Script (expand)
    from timeit import timeit
    setup = """if 1:
        from _decimal import Decimal
        d1,d2 = Decimal(1.414), Decimal('0.01')
    """
    for _ in range(2):
        r0 = timeit(s0 := f'd1.quantize (d2)', setup)
        r1 = timeit(s1 := f'd1.quantize1(d2)', setup)
        r2 = timeit(s2 := f'd1.quantize2(d2)', setup)
    
    print(s0, r0, 1 + (1 - r0 / r0))
    print(s1, r1, 1 + (1 - r1 / r0))
    print(s2, r2, 1 + (1 - r2 / r0))

Observations:

  • The number of arguments had little to do with this.
  • The gaps seem to be consistent as long as they are equally (un)exercised.
  • The same goes for non-PGO builds and builtin modules (e.g. _sre), where the impacts may be less significant.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Windows

@neonene neonene added the type-bug An unexpected behavior, bug, or error label Aug 30, 2024
@neonene
Copy link
Contributor Author

neonene commented Aug 31, 2024

I cannot confirm this issue on 3.10, so I tried profiling a function:

  • METH_METHOD|METH_FASTCALL (as-is)
                                                 entry
Function Name                                    count
_sre_SRE_Pattern_sub                           1000000
cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD  1000000  # 3.10
cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD  1000003  # 3.14
  • METH_FASTCALL (no defining_class)
                                                 entry
Function Name                                    count
_sre_SRE_Pattern_sub_patched                   1000000
cfunction_vectorcall_FASTCALL_KEYWORDS         1001231  # 3.10
cfunction_vectorcall_FASTCALL_KEYWORDS             918  # 3.14

@neonene neonene changed the title METH_METHOD calling convention seems not so efficient METH_METHOD calling convention is now not so efficient Aug 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-C-API type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

2 participants