-
Notifications
You must be signed in to change notification settings - Fork 348
Sprite scale: Preserve performance #2389
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
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
8a2b1de
Initial work
einarf ca6aa9b
More fixes + tests
einarf d369c45
Example fixes
einarf d0a68db
Updated scale method names, and reimplimented scalar setting of scale
DragonMoffon 492ce7a
Fix examples and tutorials
DragonMoffon b39cf5d
fixing typing error
DragonMoffon 3c50ddf
linting and type pass
DragonMoffon 6744f69
last place the old method was hiding
DragonMoffon 01ca6df
perf tests and improved scale setter
DragonMoffon 1981ad5
comparing func vs unpacking and random numbers in perf test
DragonMoffon c46defd
arcade scale incorect type unit test
DragonMoffon 889d906
Merge branch 'development' into scale-tweaks
DragonMoffon File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
|
||
# Sprite Benchmark | ||
|
||
Contains performance comparison between two alternative implementations of | ||
sprite handling scaling somewhat differently. This was done at the end | ||
of arcade 3.0 to measure performance of scaling changes. | ||
|
||
This can be changed and adjusted as needed to test different scenarios. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
""" | ||
Quick and dirty system measuring differences between two sprite classes. | ||
""" | ||
import gc | ||
import math | ||
import timeit | ||
import arcade | ||
from itertools import cycle | ||
from random import random | ||
|
||
from sprite_alt import BasicSprite as SpriteA | ||
from arcade import BasicSprite as SpriteB | ||
|
||
random_numbers = cycle(tuple(random() + 0.1 for _ in range(1009))) | ||
|
||
N = 100 | ||
MEASUREMENT_CONFIG = [ | ||
{"name": "populate", "number": N, "measure_method": "populate", "post_methods": ["flush"]}, | ||
{"name": "scale_set", "number": N, "measure_method": "scale_set", "post_methods": []}, | ||
{"name": "scale_set_uniform", "number": N, "measure_method": "scale_set_uniform", "post_methods": []}, | ||
{"name": "scale_mult", "number": N, "measure_method": "scale_mult", "post_methods": []}, | ||
{"name": "scale_mult_uniform", "number": N, "measure_method": "scale_mult_uniform", "post_methods": []}, | ||
] | ||
|
||
|
||
class Measurement: | ||
def __init__(self, avg=0.0, min=0.0, max=0.0): | ||
self.avg = avg | ||
self.min = min | ||
self.max = max | ||
|
||
@classmethod | ||
def from_values(cls, values: list[float]) -> "Measurement": | ||
return cls(avg=sum(values) / len(values), min=min(values), max=max(values)) | ||
|
||
# TODO: Compare measurements | ||
|
||
def __str__(self): | ||
return f"avg={self.avg}, min={self.min}, max={self.max}" | ||
|
||
|
||
class SpriteCollection: | ||
sprite_type = None | ||
sprite_count = 100_000 | ||
|
||
def __init__(self): | ||
self.spritelist = arcade.SpriteList(lazy=True, capacity=self.sprite_count) | ||
|
||
def flush(self): | ||
"""Remove all sprites from the spritelist.""" | ||
self.spritelist.clear() | ||
|
||
def populate(self): | ||
"""Populate the spritelist with sprites.""" | ||
texture = arcade.load_texture(":assets:images/items/coinBronze.png") | ||
N = int(math.sqrt(self.sprite_count)) | ||
for y in range(N): | ||
for x in range(N): | ||
self.spritelist.append( | ||
self.sprite_type( | ||
texture=texture, | ||
center_x=x * 64, | ||
center_y=y * 64, | ||
scale=(1.0, 1.0), | ||
) | ||
) | ||
|
||
# Scale | ||
def scale_set(self): | ||
"""Set the scale of all sprites.""" | ||
for sprite in self.spritelist: | ||
sprite.scale = next(random_numbers) | ||
|
||
def scale_set_uniform(self): | ||
"""Set the scale of all sprites.""" | ||
for sprite in self.spritelist: | ||
sprite.scale_set_uniform(next(random_numbers)) | ||
|
||
def scale_mult_uniform(self): | ||
"""Multiply the scale of all sprites.""" | ||
for sprite in self.spritelist: | ||
sprite.scale_multiply_uniform(next(random_numbers)) | ||
|
||
def scale_mult(self): | ||
"""Multiply the scale of all sprites uniformly.""" | ||
for sprite in self.spritelist: | ||
sprite.multiply_scale(next(random_numbers, 1.0)) | ||
|
||
# Rotate | ||
# Move | ||
# Collision detection | ||
|
||
|
||
class SpriteCollectionA(SpriteCollection): | ||
sprite_type = SpriteA | ||
|
||
class SpriteCollectionB(SpriteCollection): | ||
sprite_type = SpriteB | ||
|
||
|
||
def measure_sprite_collection(collection: SpriteCollection, number=10) -> dict[str, Measurement]: | ||
"""Perform actions on the sprite collections and measure the time.""" | ||
print(f"Measuring {collection.__class__.__name__}...") | ||
measurements: dict[str, Measurement] = {} | ||
|
||
for config in MEASUREMENT_CONFIG: | ||
name = config["name"] | ||
number = config["number"] | ||
measure_method = getattr(collection, config["measure_method"]) | ||
post_methods = [getattr(collection, method) for method in config.get("post_methods", [])] | ||
|
||
results = [] | ||
try: | ||
for _ in range(number): | ||
results.append(timeit.timeit(measure_method, number=1)) | ||
for method in post_methods: | ||
method() | ||
measurement = Measurement.from_values(results) | ||
measurements[name] = measurement | ||
print(f"{name}: {measurement}") | ||
except Exception as e: | ||
print(f"Failed to measure {name}: {e}") | ||
|
||
collection.flush() | ||
collection.populate() | ||
gc_until_nothing() | ||
|
||
return measurements | ||
|
||
|
||
def gc_until_nothing(): | ||
"""Run the garbage collector until no more objects are found.""" | ||
while gc.collect(): | ||
pass | ||
|
||
|
||
def main(): | ||
a = SpriteCollectionA() | ||
b = SpriteCollectionB() | ||
|
||
m1 = measure_sprite_collection(a) | ||
gc_until_nothing() | ||
m2 = measure_sprite_collection(b) | ||
# FIXME: Compare measurements | ||
|
||
|
||
if __name__ == '__main__': | ||
main() |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.