Skip to content

Optimise ImageColor using functools.lru_cache#7657

Merged
radarhere merged 1 commit intopython-pillow:mainfrom
hugovk:optimise-imagecolor
Dec 31, 2023
Merged

Optimise ImageColor using functools.lru_cache#7657
radarhere merged 1 commit intopython-pillow:mainfrom
hugovk:optimise-imagecolor

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
@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

2 participants