#๐Ÿ”’ Why is Python3.13 slower? How do I fix it?

157 messages ยท Page 1 of 1 (latest)

crude smelt
#

Python3.13rc1 seems to be about 20-25% slower than Python3.12.4.
Platform: M1 Mac running MacOS Sonoma 14.5

fierce wigeonBOT
#

@crude smelt

Python help channel opened

Remember to:

  • Ask your Python question, not if you can ask or if there's an expert who can help.
  • Show a code sample as text (rather than a screenshot) and the error message, if you've got one.
  • Explain what you expect to happen and what actually happens.

:warning: Do not pip install anything that isn't related to your question, especially if asked to over DMs.

brazen vortex
#

If you have a benchmark, you should report an issue to cpython

#

It's still in beta after all

crude smelt
brazen vortex
#

it's still in rc after all

crude smelt
#

Yes, but this is the second to last rc and I'm worried.

#

I've been holding off saying that since early betas.

brazen vortex
#

!paste don't upload text files

fierce wigeonBOT
#
Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.

crude smelt
brazen vortex
#

And the code you ran?

crude smelt
#

Way to long to paste here.

vague orbit
#

!pastebin

brazen vortex
fierce wigeonBOT
#
Pasting large amounts of code

If your code is too long to fit in a codeblock in Discord, you can paste your code here:
https://paste.pythondiscord.com/

After pasting your code, save it by clicking the Paste! button in the bottom left, or by pressing CTRL + S. After doing that, you will be navigated to the new paste's page. Copy the URL and post it here so others can see it.

crude smelt
brazen vortex
#

then make a git repo

crude smelt
#

I have one.

brazen vortex
crude smelt
brazen vortex
#

Test it with more versions of python. Which version introduced the regression?

crude smelt
#

It was fast in 3.11, even faster in 3.12, and then slow in 3.13

brazen vortex
#

test on different patch versions. i.e. 3.12.4, 3.12.3, etc

#

also test different 3.13 betas

crude smelt
crude smelt
brazen vortex
#

Could it be related to the GIL?

#

How did you install/build python?

marsh path
#

How are you installing/compiling Python?

crude smelt
#

I don't know. It seems that len takes longer in 3.13, and this function:

def detect(self, text):
        i = 0
        for char in text:
            if self.peek(i) != char:
                return False
            i += 1
        return True

Took significantly longer in 3.13 than 3.12.4

#

len takes a decent amount longer, but not that much.

brazen vortex
#

!pep 703 probably related to this

fierce wigeonBOT
brazen vortex
#

It says there's an option to reenable it

crude smelt
maiden parcel
#

The GIL is still enabled by default in 3.13

brazen vortex
#

Hm....

smoky basalt
#

can you find some minimal example that exhibits the behavior?

crude smelt
#

!paste

#

I'll paste CProfile results there.

marsh path
#

What class is detect from? I want to check it in Linux and Windows x86

smoky basalt
#

if it is len of something that it an issue getting an example shouldn't be hard

crude smelt
crude smelt
crude smelt
brazen vortex
sonic grail
#

did you configure with --with-lto and whatnot

crude smelt
#

I guess its just my specific use cases, but its really harming my program's performance.

crude smelt
civic ibex
#

So itโ€™ll be using whatever flags the release manager decided to build the release with

brazen vortex
maiden parcel
#

It's probably worth reporting a bug to CPython for this, especially if you can isolate your benchmark code to a specific isolated sample that runs slower in 3.13 than 3.12

crude smelt
brave granite
#

Write the issue first with the details you have now.

sonic grail
#

i'm wondering if the RC has optimizations disabled

marsh path
#

Are you running this in pure Python or cythonized?

maiden parcel
#

If you're using CProfile specifically, some of the changes may also be due to changes in how monitoring and reporting work; I think that's changed a lot

#

Though Ned would know more about that

civic ibex
crude smelt
crude smelt
#

CProfile was just to help find the issue.

marsh path
crude smelt
#

I have to go now, but I'll check back here later and see about writing up an issue.

sonic grail
#

i'm going to build it manually and run some benchmarks

crude smelt
#

Let me double check this to see if there's a difference

civic ibex
#

Make sure your CPU isnโ€™t busy with anything else as well, that can significantly skew results

crude smelt
#

Without CProfile:

python3.12 Aardvark\ Interpreter/performance-test.py 6.09s user 0.16s system 98% cpu 6.468 total
python3.13 Aardvark\ Interpreter/performance-test.py 7.34s user 0.17s system 95% cpu 7.619 total

crude smelt
crude smelt
#

About the same ratio

#

Be back later

marsh path
#

Oh, it's beta4. Let me check RC1

sonic grail
#

oh damn it, i just built beta 4

marsh path
#

Might it be a issue with optimization of the macOS binary, or somehow running the x86 code instead of Arm?

sonic grail
#

running performance-test.py on x86 gave no real difference between 3.12 and 3.13

sonic grail
#

no, RC1 built locally

#

3.13 seems to be slightly faster than 3.12, based on these benchmarks

marsh path
sonic grail
#

i bet it's ARM

#

that's still worthy of a bug report, though

marsh path
#

Does the macOS build use ./configure and make? If so, sysconfig.get_config_var('OPT') might give a clue.

sonic grail
#

i think so

#

@crude smelt can you tell use what that outputs?

marsh path
#

sysconfig.get_config_var('CONFIG_ARGS') might also help, if it works

crude smelt
crude smelt
sonic grail
#

i know, my guess is that the slowdown is ARM-related

crude smelt
#

It's still an issue though

sonic grail
#

looks like it could be. file a bug report on cpython

crude smelt
#

I plan to. Except I still don't know the root cause or what exactly makes it slower.

sonic grail
#

if you could send the logs from cProfile, then you can see what function is taking longer

marsh path
crude smelt
#

Well, its a lot of them

crude smelt
marsh path
#

How's 3.12?

sonic grail
#

that's why we have a pastebin

crude smelt
brave granite
sonic grail
#

oh, i didn't see that

crude smelt
# crude smelt '-DNDEBUG -g -O3 -Wall'

3.12 is "'-C' '--enable-framework' '--enable-universalsdk=/' '--with-universal-archs=universal2' '--with-computed-gotos' '--without-ensurepip' '--with-openssl=/tmp/_py/libraries/usr/local' '--enable-optimizations' '--with-lto' 'TCLTK_CFLAGS=-I/tmp/_py/libraries/usr/local/include' 'TCLTK_LIBS=-ltcl8.6 -ltk8.6' 'LDFLAGS=-g' 'CFLAGS=-g' 'CC=clang'"

sonic grail
#

oh

crude smelt
#

That could be part of the issue right there.

sonic grail
#

i think they forgot to enable optimizations for that build

crude smelt
#

I guess so. But would that account for 25%??

sonic grail
#

yes

crude smelt
#

Okay, then I guess we found our problem

marsh path
#

Are you sure you're comparing the same var? "OPT" versus "OPT" or "CONFIG_ARGS" versus "CONFIG_ARGS"?

crude smelt
#

I just copied without paying attention. Let me look...

#

Oh, yeah, I did different ones

#

OPT:

3.13rc1: -DNDEBUG -g -O3 -Wall
3.12.4: -DNDEBUG -g -O3 -Wall

CONFIG_ARGS:

3.13rc1: '--enable-framework' '--with-framework-name=Python' '--enable-universalsdk=/' '--with-universal-archs=universal2' '--enable-optimizations' '--with-lto' '--without-ensurepip' '--with-system-libmpdec' '--with-openssl=/Users/nad/release-tools/macos-installer/installer/variant/binaries/build/libraries/usr/local' 'LIBLZMA_CFLAGS=-I/Users/nad/release-tools/macos-installer/installer/variant/binaries/build/libraries/usr/local/include' 'LIBLZMA_LIBS=-L/Users/nad/release-tools/macos-installer/installer/variant/binaries/build/libraries/usr/local/lib -llzma' 'LIBMPDEC_CFLAGS=-I/Users/nad/release-tools/macos-installer/installer/variant/binaries/build/libraries/usr/local/include' 'LIBMPDEC_LIBS=-L/Users/nad/release-tools/macos-installer/installer/variant/binaries/build/libraries/usr/local/lib -lmpdec -lm' 'LIBSQLITE3_CFLAGS=-I/Users/nad/release-tools/macos-installer/installer/variant/binaries/build/libraries/usr/local/include' 'LIBSQLITE3_LIBS=-L/Users/nad/release-tools/macos-installer/installer/variant/binaries/build/libraries/usr/local/lib -lsqlite3' 'TCLTK_CFLAGS=-I/Users/nad/release-tools/macos-installer/installer/variant/binaries/build/libraries/usr/local/include' 'TCLTK_LIBS=-L/Users/nad/release-tools/macos-installer/installer/variant/binaries/build/libraries/usr/local/lib -ltcl -ltk' 'CC=clang'
3.12.4: '-C' '--enable-framework' '--enable-universalsdk=/' '--with-universal-archs=universal2' '--with-computed-gotos' '--without-ensurepip' '--with-openssl=/tmp/_py/libraries/usr/local' '--enable-optimizations' '--with-lto' 'TCLTK_CFLAGS=-I/tmp/_py/libraries/usr/local/include' 'TCLTK_LIBS=-ltcl8.6 -ltk8.6' 'LDFLAGS=-g' 'CFLAGS=-g' 'CC=clang'

sonic grail
#

ok, so they both are compiled with optimizations, odd

crude smelt
#

Okay, then it must be a different issue.

sonic grail
#

could you come up with a reproducer that runs slower on 3.13

smoky basalt
#

how much difference do computed gotos make? that's one flag that seems to be different unless that's on by default

#

if this is a difference it could explain a good chunk of the diff

Comments inside the CPython implementation note that using computed goto made the Python VM 15-20% faster

crude smelt
#

That could be it.

smoky basalt
#

considering it depends on a compiler extension it might not be the default, should be easy to check for someone who knows the python build setup (i.e. not me)

crude smelt
#

I'll make a build with that turned on to check

marsh path
#

Just checked, it's supposed to have computed gotos even without the config option, it's enabled by defauld on mac

crude smelt
marsh path
#

I say build it and see how it behaves ๐Ÿ˜‰

crude smelt
#

What all options should I use?

marsh path
#

I don't know the mac build system, I have doubts about framework and universal stuff. Let me check the devguide.

crude smelt
#

This is my first time ever building from source.

smoky basalt
#

enabled by default on supported compilers

#

so presumably it was enabled

crude smelt
#

Should I still build from source? I've never done this before.

marsh path
#

Erm, it might not be worth it then.

crude smelt
#

Okay

marsh path
#

Let me give you a small reproducer, if it shows the slowdown it should help filing an issue.

#
from time import process_time

class Lexer:
    def __init__(self, data):
        self.data = data
        self.index = 0

    def detect(self, text):
        i = 0
        for char in text:
            if self.peek(i) != char:
                return False
            i += 1
        return True

    def peek(self, amt=1):
        if self.index + amt < len(self.data):
            return self.data[self.index + amt]
        else:
            return None

text = "return text + indent * ' ' + '}'\n" * 200
needle = "return text + indent * ' ' + '}'\n" * 199 + "Nope\n" 
lexer = Lexer(text)
start = process_time() 
for x in range(100):
    lexer.detect(needle)
print(process_time() - start)

Please see if this is enough to show the slowdown. Adjust the numbers so it runs for a couple seconds.

crude smelt
sonic grail
#

switch the loop to like 10000 if the slowdown is too miniscule

crude smelt
#

10,000 Repetitions:

3.12.4: 7.742122s
3.13rc1: 8.309326s

winter delta
#

that makes sure that you're doing an apples-to-apples comparison: the same build options used to build both interpreters, on the same machine, with the same compiler, etc

crude smelt
winter delta
#

oh, then I misunderstood

#

I didn't realize python.org has pre-built macOS binaries for the beta releases. TIL

marsh path
#

3.13 is consistently faster than 3.12 for me on Windows x86 with that reproducer.

crude smelt
brazen vortex
#

Anyone tested on linux ARM?

crude smelt
#

I don't have it so I didn't.

fierce wigeonBOT
#
Python help channel closed

This help channel has been closed and it's no longer possible to send messages here. If your question wasn't answered, feel free to create a new post in #1035199133436354600. To maximize your chances of getting a response, check out this guide on asking good questions.