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 ImageColor using functools.lru_cache #7657

Merged
merged 1 commit into from Dec 31, 2023

Conversation

hugovk
Copy link
Member

@hugovk hugovk commented Dec 30, 2023

Follow on from #7632, use functools.lru_cache to cache the computed colours of ImageColor.getrgb(color) and ImageColor.getcolor(color, mode).

getrgb

Running these:

python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getrgb('red')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getrgb('#defdef')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getrgb('#00f')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getrgb('rgb(0,255,0)')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getrgb('rgba(255,0,0,0)')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getrgb('hsl(0.1,99.2%,50.3%)')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getrgb('hsv(360.,100.0%,100%)')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getrgb('HSB(0,100%,50%)')"

# all of them:
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getrgb('red'); ImageColor.getrgb('#defdef'); ImageColor.getrgb('#00f'); ImageColor.getrgb('rgb(0,255,0)'); ImageColor.getrgb('rgba(255,0,0,0)'); ImageColor.getrgb('hsl(0.1,99.2%,50.3%)'); ImageColor.getrgb('hsv(360.,100.0%,100%)'); ImageColor.getrgb('HSB(0,100%,50%)')"

Gives an improvement of 3.1 - 91.4 times faster:

color main lru_cache times faster
red 5000000 loops, best of 5: 0.0872 usec per loop 10000000 loops, best of 5: 0.0285 usec per loop 3.1
#defdef 200000 loops, best of 5: 1.05 usec per loop 10000000 loops, best of 5: 0.0288 usec per loop 36.5
#00f 500000 loops, best of 5: 0.575 usec per loop 10000000 loops, best of 5: 0.0287 usec per loop 20.0
rgb(0,255,0) 200000 loops, best of 5: 1.53 usec per loop 10000000 loops, best of 5: 0.029 usec per loop 52.8
rgba(255,0,0,0) 100000 loops, best of 5: 2.46 usec per loop 10000000 loops, best of 5: 0.029 usec per loop 84.8
hsl(0.1,99.2%,50.3%) 100000 loops, best of 5: 2.56 usec per loop 10000000 loops, best of 5: 0.0288 usec per loop 88.9
hsv(360.,100.0%,100%) 100000 loops, best of 5: 2.68 usec per loop 10000000 loops, best of 5: 0.029 usec per loop 92.4
HSB(0,100%,50%) 100000 loops, best of 5: 2.66 usec per loop 10000000 loops, best of 5: 0.029 usec per loop 91.7
all of them 20000 loops, best of 5: 14.3 usec per loop 1000000 loops, best of 5: 0.221 usec per loop 64.7

getcolor

Running these:

python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getcolor('red', 'RGB')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getcolor('red', 'RGBA')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getcolor('red', 'L')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getcolor('red', 'LA')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getcolor('red', '1')"
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getcolor('red', 'HSV')"

# all of them:
python3 -m timeit --unit usec -s "from PIL import ImageColor" "ImageColor.getcolor('red', 'RGB'); ImageColor.getcolor('red', 'RGBA'); ImageColor.getcolor('red', 'L'); ImageColor.getcolor('red', 'LA'); ImageColor.getcolor('red', '1'); ImageColor.getcolor('red', 'HSV')"

Gives an improvement of 5.1 - 19.6 times faster:

mode main lru_cache times faster
RGB 1000000 loops, best of 5: 0.21 usec per loop 10000000 loops, best of 5: 0.0386 usec per loop 5.4
RGBA 1000000 loops, best of 5: 0.232 usec per loop 10000000 loops, best of 5: 0.0381 usec per loop 6.1
L 1000000 loops, best of 5: 0.28 usec per loop 10000000 loops, best of 5: 0.0381 usec per loop 7.3
LA 1000000 loops, best of 5: 0.292 usec per loop 10000000 loops, best of 5: 0.0388 usec per loop 7.5
1 1000000 loops, best of 5: 0.28 usec per loop 10000000 loops, best of 5: 0.038 usec per loop 7.4
HSV 500000 loops, best of 5: 0.761 usec per loop 10000000 loops, best of 5: 0.0389 usec per loop 19.6
all of them 100000 loops, best of 5: 2.16 usec per loop 1000000 loops, best of 5: 0.261 usec per loop 8.3

@radarhere radarhere merged commit 0988703 into python-pillow:main Dec 31, 2023
56 checks passed
@hugovk hugovk deleted the optimise-imagecolor branch December 31, 2023 11:41
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.

None yet

2 participants