diff --git a/.gitignore b/.gitignore index 3a623fd213..573a50120b 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ .DS_Store .coverage .dmypy.json +.asv .idea .mypy_cache __pycache__ diff --git a/asv.conf.json b/asv.conf.json new file mode 100644 index 0000000000..575cb922c2 --- /dev/null +++ b/asv.conf.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "project": "colour", + "project_url": "https://www.colour-science.org/", + "repo": ".", + "branches": ["feature/benchmarks"], + "environment_type": "virtualenv", + "env_dir": ".asv/env", + "results_dir": ".asv/results", + "html_dir": ".asv/html", + "matrix": {"req": {"poetry-core": []}} +} diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/benchmarks/colour/__init__.py b/benchmarks/colour/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/benchmarks/colour/models/__init__.py b/benchmarks/colour/models/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/benchmarks/colour/models/cie_xyy.py b/benchmarks/colour/models/cie_xyy.py new file mode 100644 index 0000000000..6d706e3b5d --- /dev/null +++ b/benchmarks/colour/models/cie_xyy.py @@ -0,0 +1,36 @@ +""" +"colour.models" sub-package Benchmarks +====================================== +""" + + +import colour + +from benchmarks.factories import IJ_suites_factory, IJK_suites_factory + +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + + +IJK_suites_factory( + [ + colour.models.XYZ_to_xyY, + colour.models.xyY_to_XYZ, + colour.models.xyY_to_xy, + colour.models.XYZ_to_xy, + ], + __name__, +) + + +IJ_suites_factory( + [ + colour.models.xy_to_XYZ, + colour.models.xy_to_xyY, + ], + __name__, +) diff --git a/benchmarks/factories/__init__.py b/benchmarks/factories/__init__.py new file mode 100644 index 0000000000..cbaae6a152 --- /dev/null +++ b/benchmarks/factories/__init__.py @@ -0,0 +1,130 @@ +""" +Suite Factories +=============== +""" + + +import numpy as np +import sys +from functools import partial + +from colour.hints import Callable, List, Optional, Sequence + +__author__ = "Colour Developers" +__copyright__ = "Copyright 2013 Colour Developers" +__license__ = "New BSD License - https://opensource.org/licenses/BSD-3-Clause" +__maintainer__ = "Colour Developers" +__email__ = "colour-developers@colour-science.org" +__status__ = "Production" + +__all__ = [ + "Suite", + "suites_factory", + "I_suites_factory", + "IJ_suites_factory", + "IJK_suites_factory", +] + + +class Suite: + """ + Define a benchmark suite for *Standard Definition*, *High Definition* and + *Ultra High Definition* resolution data. + """ + + def time_sd(self): + """ + Execute underlying callable on *Standard Definition* resolution data. + """ + + if hasattr(self, "_data_sd"): + self._callable(self._data_sd) + + def time_hd(self): + """ + Execute underlying callable on *High Definition* resolution data. + """ + + if hasattr(self, "_data_hd"): + self._callable(self._data_hd) + + def time_uhd(self): + """ + Execute underlying callable on *Ultra High Definition* resolution data. + """ + + if hasattr(self, "_data_uhd"): + self._callable(self._data_uhd) + + +def suites_factory( + callables: Sequence, + module: str = __name__, + data: Optional[Sequence[Callable]] = None, +) -> List[Suite]: + """ + Produce a benchmark suites for given callables. + + Parameters + ---------- + callables + Callables to produce benchmark suites for. + module + Module to set the benchmark suites into. + data + *Standard Definition*, *High Definition* and *Ultra High Definition* + resolution data + + Returns + ------- + :class:`list` + Benchmark suites + """ + + classes = [] + + for callable_ in callables: + class_ = type(callable_.__name__, (Suite,), {}) + + class_._callable = staticmethod(callable_) + + class_._data_sd = data[0] + class_._data_hd = data[1] + class_._data_uhd = data[2] + + classes.append(classes) + + setattr(sys.modules[module], f"{callable_.__name__}_Suite", class_) + + return classes + + +np.random.seed(16) + + +I_suites_factory = partial( + suites_factory, + data=( + np.random.random([720, 1280]), + np.random.random([1080, 1920]), + np.random.random([2160, 3840]), + ), +) + +IJ_suites_factory = partial( + suites_factory, + data=( + np.random.random([720, 1280, 2]), + np.random.random([1080, 1920, 2]), + np.random.random([2160, 3840, 2]), + ), +) + +IJK_suites_factory = partial( + suites_factory, + data=( + np.random.random([720, 1280, 3]), + np.random.random([1080, 1920, 3]), + np.random.random([2160, 3840, 3]), + ), +) diff --git a/pyproject.toml b/pyproject.toml index 4eb3b429d6..842fb3eeab 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,7 @@ numpy = ">= 1.19, < 2" scipy = ">= 1.5, < 2" typing-extensions = ">= 4, < 5" # Convenience for Google Colab. +asv = { version = "*", optional = true } matplotlib = { version = ">= 3.2, != 3.5.0, != 3.5.1", optional = true } networkx = { version = ">= 2, < 3", optional = true } pandas = { version = ">= 1, < 2", optional = true } @@ -123,6 +124,7 @@ development = [ "toml", "twine", ] +benchmarks = [ "asv" ] graphviz = [ "pygraphviz" ] meshing = [ "trimesh" ] optional = [ "networkx", "pandas", "scikit-learn", "tqdm" ] diff --git a/requirements.txt b/requirements.txt index c798f36fa3..5b4cc9eee7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ argon2-cffi==21.3.0 argon2-cffi-bindings==21.2.0 astor==0.8.1 asttokens==2.0.5 +asv==0.5.1 attrs==21.4.0 Babel==2.9.1 backcall==0.2.0 @@ -19,7 +20,6 @@ click==8.0.4 colorama==0.4.4 coverage==6.3.2 coveralls==3.3.1 -cycler==0.11.0 debugpy==1.5.1 decorator==5.1.1 defusedxml==0.7.1 @@ -27,64 +27,60 @@ distlib==0.3.4 docopt==0.6.2 docutils==0.17.1 entrypoints==0.4 -executing==0.8.2 +executing==0.8.3 filelock==3.6.0 flake8==4.0.1 flynt==0.76 -identify==2.4.11 +identify==2.4.12 idna==3.3 -imageio==2.16.0 +imageio==2.16.1 imagesize==1.3.0 -importlib-metadata==4.11.1 +importlib-metadata==4.11.3 iniconfig==1.1.1 -invoke==1.6.0 -ipykernel==6.9.1 -ipython==8.1.0 +invoke==1.7.0 +ipykernel==6.9.2 +ipython==8.1.1 ipython-genutils==0.2.0 -ipywidgets==7.6.5 +ipywidgets==7.7.0 jedi==0.18.1 Jinja2==3.0.3 -joblib==1.1.0 jsonschema==4.4.0 jupyter==1.0.0 jupyter-client==7.1.2 -jupyter-console==6.4.0 +jupyter-console==6.4.3 jupyter-core==4.9.2 jupyterlab-pygments==0.1.2 -jupyterlab-widgets==1.0.2 +jupyterlab-widgets==1.1.0 keyring==23.5.0 -kiwisolver==1.3.2 latexcodec==2.0.1 -MarkupSafe==2.1.0 -matplotlib==3.4.3 +MarkupSafe==2.1.1 matplotlib-inline==0.1.3 mccabe==0.6.1 mistune==0.8.4 -mypy==0.931 +mypy==0.941 mypy-extensions==0.4.3 -nbclient==0.5.11 -nbconvert==6.4.2 -nbformat==5.1.3 +nbclient==0.5.13 +nbconvert==6.4.4 +nbformat==5.2.0 nest-asyncio==1.5.4 -networkx==2.6.3 nodeenv==1.6.0 -notebook==6.4.8 -numpy==1.22.2 +notebook==6.4.10 +numpy==1.22.3 packaging==21.3 -pandas==1.4.1 pandocfilters==1.5.0 parso==0.8.3 pathspec==0.9.0 pexpect==4.8.0 pickleshare==0.7.5 Pillow==9.0.1 -pip==21.3.1 +pip==22.0.4 pkginfo==1.8.2 platformdirs==2.5.1 pluggy==1.0.0 pre-commit==2.17.0 prometheus-client==0.13.1 prompt-toolkit==3.0.28 +psutil==5.9.0 ptyprocess==0.7.0 pure-eval==0.2.2 py==1.11.0 @@ -96,27 +92,25 @@ pydata-sphinx-theme==0.8.0 pydocstyle==6.1.1 pyflakes==2.4.0 Pygments==2.11.2 -pygraphviz==1.9 pyparsing==3.0.7 pyrsistent==0.18.1 -pytest==7.0.1 +pytest==7.1.1 pytest-cov==3.0.0 python-dateutil==2.8.2 -pytz==2021.3 -pyupgrade==2.31.0 +pytz==2022.1 +pyupgrade==2.31.1 PyYAML==6.0 pyzmq==22.3.0 qtconsole==5.2.2 QtPy==2.0.1 -readme-renderer==32.0 +readme-renderer==34.0 requests==2.27.1 requests-toolbelt==0.9.1 restructuredtext-lint==1.4.0 rfc3986==2.0.0 -scikit-learn==1.0.2 scipy==1.8.0 Send2Trash==1.8.0 -setuptools==60.5.0 +setuptools==60.9.3 six==1.16.0 snowballstemmer==2.2.0 soupsieve==2.3.1 @@ -129,23 +123,20 @@ sphinxcontrib-jsmath==1.0.1 sphinxcontrib-qthelp==1.0.3 sphinxcontrib-serializinghtml==1.1.5 stack-data==0.2.0 -terminado==0.13.1 +terminado==0.13.3 testpath==0.6.0 -threadpoolctl==3.1.0 tokenize-rt==4.2.1 toml==0.10.2 tomli==2.0.1 tornado==6.1 -tqdm==4.62.3 +tqdm==4.63.0 traitlets==5.1.1 -trimesh==3.10.2 twine==3.8.0 -types-setuptools==57.4.9 typing_extensions==4.1.1 -urllib3==1.26.8 -virtualenv==20.13.2 +urllib3==1.26.9 +virtualenv==20.13.4 wcwidth==0.2.5 webencodings==0.5.1 wheel==0.37.1 -widgetsnbextension==3.5.2 +widgetsnbextension==3.6.0 zipp==3.7.0 diff --git a/tasks.py b/tasks.py index 873f92db3b..c46ad74ac3 100644 --- a/tasks.py +++ b/tasks.py @@ -33,6 +33,7 @@ "clean", "formatting", "quality", + "benchmarks", "precommit", "tests", "examples", @@ -217,6 +218,21 @@ def quality( ctx.run("rst-lint README.rst") +@task +def benchmarks(ctx: Context): + """ + Run the *Airspeed Velocity* benchmarks. + + Parameters + ---------- + ctx + Context. + """ + + message_box('Running "Airspeed Velocity" benchmarks...') + ctx.run("asv run") + + @task def precommit(ctx: Context): """