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

Optimise ImageMode.getmode using functools.lru_cache #7641

Merged
merged 2 commits into from
Dec 26, 2023

Conversation

hugovk
Copy link
Member

@hugovk hugovk commented Dec 26, 2023

Use functools.lru_cache instead of our own global cache, to only cache those which are requested.

With no argument, lru_cache defaults to maxsize=128, plenty for the 33 valid inputs.

https://docs.python.org/3/library/functools.html#functools.lru_cache

Performance improves for all the following cases.

A mode from the top half: 33.6 -> 28.5 nsec

Before and after:

python3 -m timeit -s "from PIL import ImageMode" "ImageMode.getmode('RGB')"
10000000 loops, best of 5: 33.6 nsec per looppython3 -m timeit -s "from PIL import ImageMode" "ImageMode.getmode('RGB')"
10000000 loops, best of 5: 28.5 nsec per loop

A mapping mode from the bottom half: 36 -> 28.9 nsec

python3 -m timeit -s "from PIL import ImageMode" "ImageMode.getmode('I;16N')"
10000000 loops, best of 5: 36 nsec per looppython3 -m timeit -s "from PIL import ImageMode" "ImageMode.getmode('I;16N')"
10000000 loops, best of 5: 28.9 nsec per loop

All modes: 1.25 -> 1.01 usec

python3 -m timeit -s "from PIL import ImageMode" "ImageMode.getmode('1'); ImageMode.getmode('L'); ImageMode.getmode('I'); ImageMode.getmode('F'); ImageMode.getmode('P'); ImageMode.getmode('RGB'); ImageMode.getmode('RGBX'); ImageMode.getmode('RGBA'); ImageMode.getmode('CMYK'); ImageMode.getmode('YCbCr'); ImageMode.getmode('LAB'); ImageMode.getmode('HSV'); ImageMode.getmode('RGBa'); ImageMode.getmode('BGR;15'); ImageMode.getmode('BGR;16'); ImageMode.getmode('BGR;24'); ImageMode.getmode('LA'); ImageMode.getmode('La'); ImageMode.getmode('PA'); ImageMode.getmode('I;16'); ImageMode.getmode('I;16S'); ImageMode.getmode('I;16L'); ImageMode.getmode('I;16LS'); ImageMode.getmode('I;16B'); ImageMode.getmode('I;16BS'); ImageMode.getmode('I;16N'); ImageMode.getmode('I;16NS'); ImageMode.getmode('I;32'); ImageMode.getmode('I;32B'); ImageMode.getmode('I;32L'); ImageMode.getmode('I;32S'); ImageMode.getmode('I;32BS'); ImageMode.getmode('I;32LS')"
200000 loops, best of 5: 1.25 usec per looppython3 -m timeit -s "from PIL import ImageMode" "ImageMode.getmode('1'); ImageMode.getmode('L'); ImageMode.getmode('I'); ImageMode.getmode('F'); ImageMode.getmode('P'); ImageMode.getmode('RGB'); ImageMode.getmode('RGBX'); ImageMode.getmode('RGBA'); ImageMode.getmode('CMYK'); ImageMode.getmode('YCbCr'); ImageMode.getmode('LAB'); ImageMode.getmode('HSV'); ImageMode.getmode('RGBa'); ImageMode.getmode('BGR;15'); ImageMode.getmode('BGR;16'); ImageMode.getmode('BGR;24'); ImageMode.getmode('LA'); ImageMode.getmode('La'); ImageMode.getmode('PA'); ImageMode.getmode('I;16'); ImageMode.getmode('I;16S'); ImageMode.getmode('I;16L'); ImageMode.getmode('I;16LS'); ImageMode.getmode('I;16B'); ImageMode.getmode('I;16BS'); ImageMode.getmode('I;16N'); ImageMode.getmode('I;16NS'); ImageMode.getmode('I;32'); ImageMode.getmode('I;32B'); ImageMode.getmode('I;32L'); ImageMode.getmode('I;32S'); ImageMode.getmode('I;32BS'); ImageMode.getmode('I;32LS')"
200000 loops, best of 5: 1.01 usec per loop

src/PIL/ImageMode.py Outdated Show resolved Hide resolved
Co-authored-by: Andrew Murray <3112309+radarhere@users.noreply.github.com>
@radarhere radarhere merged commit 1e8bad8 into python-pillow:main Dec 26, 2023
54 checks passed
@hugovk hugovk deleted the optimise-imagemode branch December 27, 2023 05:10
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.

2 participants