Optimise `ImageMode.getmode` using `functools.lru_cache` by hugovk · Pull Request #7641 · python-pillow/Pillow

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