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

Performance gap of match statements of classes compared with equivalent Python 3.9 code #92868

Open
tonybaloney opened this issue May 17, 2022 · 3 comments
Assignees
Labels
performance type-bug

Comments

@tonybaloney
Copy link
Contributor

@tonybaloney tonybaloney commented May 17, 2022

Im doing some micro-benchmarks of the match statement.

The following comparison shows two functionally equivalent functions of the class matching pattern in the match statement.

class Driver:
    def __init__(self, name, team, **extra):
        self.name = name
        self.team = team
        self.extra = extra

def bench_class_matching_statement():
    drivers = [
        Driver(name="Max Verstappen", team="Red Bull", ),
        Driver(name="Sergio Perez", team="Red Bull", ),
        Driver(name="Charles Leclerc", team="Ferrari", ),
        Driver(name="Lewis Hamilton", team="Mercedes", ),
    ]

    for _ in range(100_000):
        for driver in drivers:
            match driver:
                case Driver(name="Max Verstappen"): desc = f"Max Verstappen, the current world #1"
                case Driver(name=name, team="Ferrari"): desc = f"{name}, a Ferrari driver!! 🐎"
                case Driver(name=name, team=team): desc = f"{name}, a {team} driver."
                case _: desc = "Invalid request"
            # print(desc)


def bench_class_matching_logical():
    drivers = [
        Driver(name="Max Verstappen", team="Red Bull", ),
        Driver(name="Sergio Perez", team="Red Bull", ),
        Driver(name="Charles Leclerc", team="Ferrari", ),
        Driver(name="Lewis Hamilton", team="Mercedes", ),
    ]

    for _ in range(100_000):
        for driver in drivers:
            if not isinstance(driver, Driver):
                desc = "Invalid request"
            elif driver.name == "Max Verstappen":
                desc = f"Max Verstappen, the current world #1"
            elif driver.team == "Ferrari": 
                desc = f"{driver.name}, a Ferrari driver!! 🐎"
            else:
                desc = f"{driver.name}, a {driver.team} driver."
            # print(desc)

Python 3.11 executes bench_class_matching_statement() at 4x the execution time of bench_class_matching_logical()
Python 3.10 executes bench_class_matching_statement() at 2.5x the execution time of bench_class_matching_logical()

Python 3.11b1 is showing a speedup of both functions (which is great).

Pattern matching for sequences and mapping is faster than the equivalent Python code, but for classes it is significantly slower.

@tonybaloney tonybaloney added the type-bug label May 17, 2022
@tonybaloney
Copy link
Contributor Author

@tonybaloney tonybaloney commented May 17, 2022

@JelleZijlstra
Copy link
Member

@JelleZijlstra JelleZijlstra commented May 17, 2022

So just to be clear, both functions are faster in 3.11 than in 3.10, but the bug is that the speedup in one of them is greater than in the other? That hardly seems like a bug.

@tonybaloney
Copy link
Contributor Author

@tonybaloney tonybaloney commented May 17, 2022

Sorry, that was unclear.

The bug is that pattern matching of classes per the spec is slower than the equivalent Python 3.9< code.

I had a conversation with Brandt about this the other week. He was working on a patch to improve the performance, so I wanted to capture this issue to track it.

FF to close if this should go somewhere else (mailing lists)

@JelleZijlstra JelleZijlstra added the performance label May 17, 2022
@tonybaloney tonybaloney changed the title Python 3.11 performance regression in match statements of classes Performance gap of match statements of classes compared with equivalent Python 3.9 code May 17, 2022
@brandtbucher brandtbucher self-assigned this May 17, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance type-bug
Projects
None yet
Development

No branches or pull requests

3 participants