Skip to content

gh-126703: add freelist for PyComplexObject's #135233

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

skirpichev
Copy link
Contributor

@skirpichev skirpichev commented Jun 7, 2025


Micro-benchmark:

Benchmark ref patch
a+b 223 ns 198 ns: 1.13x faster
a*b 236 ns 209 ns: 1.13x faster
Geometric mean (ref) 1.13x faster
# bench.py
import pyperf
from operator import add, mul
runner = pyperf.Runner()
a,b = 1+2j, -7+1.1j
runner.bench_func('a+b', add, a, b)
runner.bench_func('a*b', mul, a, b)

@corona10
Copy link
Member

corona10 commented Jun 7, 2025

@skirpichev Would you like to provide benchmark enhancement for this change?

@skirpichev
Copy link
Contributor Author

Oops, I just forgot to post one. Description updated.

@corona10
Copy link
Member

corona10 commented Jun 7, 2025

Please share the pyperformance benchmark results.
I'm not sure how often complex types are used in real-world workloads.
Microbenchmarks like this might suggest adding every built-in type to the freelist, but I don't think that's what we want.
Most of the types we've added so far are commonly used in loop-based operations.

cc @Fidget-Spinner @encukou @eendebakpt

@skirpichev skirpichev marked this pull request as draft June 7, 2025 13:51
@skirpichev
Copy link
Contributor Author

Please share the pyperformance benchmark results.

Well, it shouldn't be affected. This collection has no benchmarks for complex math at all:

$ git grep _E '[0-9.][jJ]|cmath|complex' pyperformance/data-files/benchmarks/||echo Oops
Oops

I'm not sure how often complex types are used in real-world workloads.

Probably less than floats, but not too much.

@skirpichev skirpichev marked this pull request as ready for review June 7, 2025 14:12
@encukou
Copy link
Member

encukou commented Jun 7, 2025

AFAICS, real-world workloads that don't use complex numbers will pay the price of:

  • two unused words of memory
  • the maintenance burden of a (I assume!) standard and unsurprising use of _Py_freelist

In applications that do use complex numbers, is it likely that they need to create/destroy them quickly?
IMO, an educated guess is enough to answer that, and if we've established that this is what freelists help with... I'd just trust Sergey here.

To review this I'll need to teach myself about Python's freelists; I can do that next week.

@corona10
Copy link
Member

corona10 commented Jun 7, 2025

IMO, an educated guess is enough to answer that, and if we've established that this is what freelists help with... I'd just trust Sergey here.

I believe that we use pyperformance benchmark as the real world proxy. So if there is no benchmark for it, I am unsure. At least someone needs to share the benchmark for this. If not, people will add new PR for other built-in types with a microbenchmark, which would not be worth adding. We need criteria for this.

@skirpichev
Copy link
Contributor Author

two unused words of memory

Yes, just a new empty _Py_freelists.

In applications that do use complex numbers, is it likely that they need to create/destroy them quickly?

That happens in every arithmetic operation.

Here is a benchmark with a simple sin() implementation:

Benchmark ref patch
mysin(1j) 14.0 us 12.8 us: 1.09x faster
mysin(1+1j) 15.7 us 14.4 us: 1.09x faster
Geometric mean (ref) 1.09x faster
# bench2.py
def mysin(z):
    i, lasts, s, fact, num, sign = 1, 0, z, 1, z, 1
    while s != lasts:
        lasts = s
        i += 2
        fact *= i*(i-1)
        num *= z*z
        sign *= -1
        s += num/fact*sign
    return s
import pyperf
runner = pyperf.Runner()
runner.bench_func('mysin(1j)', mysin, 1j)
runner.bench_func('mysin(1+1j)', mysin, 1+1j)

To review this I'll need to teach myself about Python's freelists

You are not alone, this is new for me as well :D IIUC (see help topic), this technique is not something, allowed for external C extensions.

If not, people will add new PR for other built-in types with a microbenchmark

I doubt we have too much built-in types. Being a built-in type is a sign from the real world too ;-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy