Skip to content

Commit 502de76

Browse files
committed
Add more benchmarks from separate perf work branch
1 parent 5577ff1 commit 502de76

1 file changed

Lines changed: 139 additions & 1 deletion

File tree

Tests/benchmarks.py

Lines changed: 139 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@
55
from __future__ import annotations
66

77
import pathlib
8+
from collections.abc import Callable
89
from io import BytesIO
910

1011
import pytest
1112

12-
from PIL import Image, ImageFilter
13+
from PIL import Image, ImageChops, ImageFilter
1314
from PIL.Image import Resampling, Transpose
1415

1516
TYPE_CHECKING = False
@@ -341,3 +342,140 @@ def test_merge(bench: BenchmarkFixture, mode: str, size: tuple[int, int]) -> Non
341342
bands = im.split()
342343
bench.extra_info["label"] = [f"merge {mode}"]
343344
bench(Image.merge, mode, bands)
345+
346+
347+
@pytest.mark.benchmark(group="allocate")
348+
@pytest.mark.parametrize("mode", MODES)
349+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
350+
def test_fill(bench: BenchmarkFixture, mode: str, size: tuple[int, int]) -> None:
351+
nbands = len(Image.new(mode, (1, 1)).getbands())
352+
color = (10, 20, 30, 40)[:nbands] if nbands > 1 else 10
353+
bench.extra_info["label"] = [f"fill {mode}"]
354+
bench(Image.new, mode, size, color)
355+
356+
357+
CHOPS_OPS = [
358+
ImageChops.add,
359+
ImageChops.subtract,
360+
ImageChops.multiply,
361+
ImageChops.screen,
362+
ImageChops.difference,
363+
ImageChops.lighter,
364+
ImageChops.darker,
365+
ImageChops.add_modulo,
366+
ImageChops.soft_light,
367+
ImageChops.hard_light,
368+
ImageChops.overlay,
369+
]
370+
371+
372+
@pytest.mark.benchmark(group="chops")
373+
@pytest.mark.parametrize("op", CHOPS_OPS, ids=lambda f: f.__name__)
374+
@pytest.mark.parametrize("mode", MODES)
375+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
376+
def test_chops(
377+
bench: BenchmarkFixture,
378+
mode: str,
379+
size: tuple[int, int],
380+
op: Callable[[Image.Image, Image.Image], Image.Image],
381+
) -> None:
382+
im1 = make_pillow_image(mode, size)
383+
im2 = make_pillow_image(mode, size, pattern_offset=1024)
384+
bench.extra_info["label"] = [op.__name__]
385+
result = bench(op, im1, im2)
386+
assert result.size == im1.size
387+
388+
389+
@pytest.mark.benchmark(group="chops")
390+
@pytest.mark.parametrize("mode", MODES)
391+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
392+
def test_invert(bench: BenchmarkFixture, mode: str, size: tuple[int, int]) -> None:
393+
im = make_pillow_image(mode, size)
394+
bench.extra_info["label"] = ["invert"]
395+
bench(ImageChops.invert, im)
396+
397+
398+
@pytest.mark.benchmark(group="chops")
399+
@pytest.mark.parametrize("mode", MODES)
400+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
401+
def test_offset(bench: BenchmarkFixture, mode: str, size: tuple[int, int]) -> None:
402+
im = make_pillow_image(mode, size)
403+
bench.extra_info["label"] = ["offset"]
404+
bench(ImageChops.offset, im, 123, 45)
405+
406+
407+
@pytest.mark.benchmark(group="histogram")
408+
@pytest.mark.parametrize("mode", MODES)
409+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
410+
def test_histogram(bench: BenchmarkFixture, mode: str, size: tuple[int, int]) -> None:
411+
im = make_pillow_image(mode, size)
412+
bench.extra_info["label"] = [f"histogram {mode}"]
413+
bench(im.histogram)
414+
415+
416+
@pytest.mark.benchmark(group="histogram")
417+
@pytest.mark.parametrize("mode", MODES)
418+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
419+
def test_histogram_masked(
420+
bench: BenchmarkFixture, mode: str, size: tuple[int, int]
421+
) -> None:
422+
im = make_pillow_image(mode, size)
423+
mask = make_pillow_image("L", size)
424+
bench.extra_info["label"] = [f"masked histogram {mode}"]
425+
bench(im.histogram, mask)
426+
427+
428+
L_MATRIX = (0.299, 0.587, 0.114, 0.0)
429+
RGB_MATRIX = (
430+
0.412, 0.357, 0.180, 0.0,
431+
0.212, 0.715, 0.072, 0.0,
432+
0.019, 0.119, 0.950, 0.0,
433+
) # fmt: skip
434+
435+
436+
@pytest.mark.benchmark(group="convert")
437+
@pytest.mark.parametrize(
438+
"mode_to, matrix",
439+
[("L", L_MATRIX), ("RGB", RGB_MATRIX)],
440+
)
441+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
442+
def test_matrix_convert(
443+
bench: BenchmarkFixture,
444+
mode_to: str,
445+
matrix: tuple[float, ...],
446+
size: tuple[int, int],
447+
) -> None:
448+
im = make_pillow_image("RGB", size)
449+
bench.extra_info["label"] = [f"matrix RGB to {mode_to}"]
450+
bench(im.convert, mode_to, matrix)
451+
452+
453+
@pytest.mark.benchmark(group="point")
454+
@pytest.mark.parametrize("mode", MODES)
455+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
456+
def test_point_lut(bench: BenchmarkFixture, mode: str, size: tuple[int, int]) -> None:
457+
im = make_pillow_image(mode, size)
458+
lut = [255 - i for i in range(256)] * len(im.getbands())
459+
bench.extra_info["label"] = [f"LUT {mode}"]
460+
bench(im.point, lut)
461+
462+
463+
@pytest.mark.benchmark(group="point")
464+
@pytest.mark.parametrize("mode", ["I", "F"])
465+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
466+
def test_point_transform(
467+
bench: BenchmarkFixture, mode: str, size: tuple[int, int]
468+
) -> None:
469+
im = make_pillow_image(mode, size)
470+
bench.extra_info["label"] = [f"transform {mode}"]
471+
bench(im.point, lambda v: v * 1.5 + 3.0)
472+
473+
474+
@pytest.mark.benchmark(group="quantize")
475+
@pytest.mark.parametrize("mode", [m for m in MODES if m in ("L", "RGB", "RGBA")])
476+
@pytest.mark.parametrize("size", SIZES, ids=_format_size)
477+
def test_quantize(bench: BenchmarkFixture, mode: str, size: tuple[int, int]) -> None:
478+
im = make_pillow_image(mode, size)
479+
bench.extra_info["label"] = [f"quantize {mode}"]
480+
result = bench(im.quantize, 256)
481+
assert result.mode == "P"

0 commit comments

Comments
 (0)