Skip to content

Optimized Rect.clipline() #3067

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

Merged
merged 2 commits into from
Aug 20, 2024

Conversation

itzpr3d4t0r
Copy link
Member

@itzpr3d4t0r itzpr3d4t0r commented Aug 19, 2024

This PR improves the speed of Rect.clipline() by 45-50% when the line intersects the rectangle, with no noticeable change when there's no intersection. The optimization comes from replacing PyBuildValue with a custom implementation to construct the return tuple.

I've also added a new macro that enables easy dispatching between the double/int custom tuple packing function we have.

I got these results:
Old

Colliding
2.2999593056738377e-06 2.571070200065151e-06
2.3999600671231747e-06 2.5393099116627127e-06
2.2999593056738377e-06 2.440720208687708e-06
2.2999593056738377e-06 2.4487898976076393e-06
2.3999600671231747e-06 2.4846897984389216e-06
Non Colliding
8.999486453831196e-07 1.0697301593609154e-06
8.999486453831196e-07 9.743399394210428e-07
8.999486453831196e-07 9.719599853269757e-07
8.999486453831196e-07 9.75440168986097e-07
8.999486453831196e-07 1.03677986189723e-06

New

Colliding
1.5999539755284786e-06 1.6530799737665803e-06
1.5999539755284786e-06 1.7165300087071954e-06
1.5999539755284786e-06 1.801859913393855e-06
1.5999539755284786e-06 1.6924298892263323e-06
1.5999539755284786e-06 1.8196600314695388e-06
Non Colliding
8.999486453831196e-07 1.036960061173886e-06
8.999486453831196e-07 1.0293898812960834e-06
8.999486453831196e-07 1.0853600455448032e-06
8.999486453831196e-07 1.0411400173325092e-06
8.999486453831196e-07 1.0053500125650316e-06

Using this test program:

from timeit import repeat
from statistics import fmean

from pygame import Rect

r = Rect(100, 100, 100, 100)

G = globals()

print("Colliding")
for _ in range(5):
    data = repeat("r.clipline(0, 0, 105, 150)", number=10, repeat=10000, globals=G)
    print(f"{min(data)} {fmean(data)}")

print("Non Colliding")
for _ in range(5):
    data = repeat("r.clipline(0, 0, 1000, 10)", number=10, repeat=10000, globals=G)
    print(f"{min(data)} {fmean(data)}")

@itzpr3d4t0r itzpr3d4t0r added Performance Related to the speed or resource usage of the project rect pygame.rect labels Aug 19, 2024
@itzpr3d4t0r itzpr3d4t0r requested a review from a team as a code owner August 19, 2024 10:41
Copy link
Member

@damusss damusss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice optimization! :)

Copy link
Member

@ankith26 ankith26 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for the PR 🎉

@ankith26 ankith26 added this to the 2.5.2 milestone Aug 20, 2024
@ankith26 ankith26 merged commit 141a75d into pygame-community:main Aug 20, 2024
26 checks passed
@itzpr3d4t0r itzpr3d4t0r deleted the rect-clipline-opt branch August 22, 2024 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Performance Related to the speed or resource usage of the project rect pygame.rect
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants