Skip to content

Commit

Permalink
🔧(benchmarks): Add benchmarks script and CI (#56)
Browse files Browse the repository at this point in the history
* 🔧(benchmarks): Add benchmarks script and CI

* Rename benchmark CI
  • Loading branch information
Isotr0py authored Aug 7, 2024
1 parent 2e34070 commit e676784
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 0 deletions.
64 changes: 64 additions & 0 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Benchmarks

on: [push, pull_request]

env:
RUSTFLAGS: -C debuginfo=0 # Do not produce debug symbols to keep memory usage down
RUST_BACKTRACE: 1

jobs:
benchmarks:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# we only use macos for fast testing
os: [macos-latest]
python-version: ['3.11']

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Create virtual environment
env:
BIN: ${{ matrix.os == 'macos-latest' && 'Scripts' || 'bin' }}
run: |
python -m venv venv
- name: Set up Rust
run: rustup show

- name: Cache Rust
uses: Swatinem/rust-cache@v2

- name: Install Plugin
run: |
brew install jpeg-xl
export DEP_JXL_LIB=/opt/homebrew/Cellar/jpeg-xl/0.10.3/lib
export DEP_BROTLI_LIB=/opt/homebrew/Cellar/brotli/1.1.0/lib
export DEP_HWY_LIB=/opt/homebrew/Cellar/highway/1.2.0/lib
source venv/bin/activate
pip install maturin
maturin develop --features dynamic
- name: Run benchmarks scripts
run: |
source venv/bin/activate
python benchmarks/benchmarks_encode.py -i test/images/bench.png -o benchmarks-results-${{ matrix.python-version }}.json
- name: Upload pytest test results
uses: actions/upload-artifact@v4
with:
name: benchmarks-results-${{ matrix.python-version }}
path: benchmarks-results-${{ matrix.python-version }}.json
# Use always() to always run this step to publish test results when there are test failures
if: ${{ always() }}


3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
/target
Cargo.lock

# Generated files
*.json

# Byte-compiled / optimized / DLL files
__pycache__/
.pytest_cache/
Expand Down
67 changes: 67 additions & 0 deletions benchmarks/benchmarks_encode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import json
import shlex
import subprocess
from argparse import ArgumentParser
from io import BytesIO
from time import time

from PIL import Image

import pillow_jxl


def encode_plugin(filename, quality, effort):
bio = BytesIO()
t = time()
Image.open(filename).save(bio, format="jxl", quality=quality, effort=effort)
d = time() - t
return len(bio.getvalue()), d


def encode_cli(filename, quality, effort):
cmd = f'cjxl -q {quality} -e {effort} "{filename}" -'
t = time()
p = subprocess.run(shlex.split(cmd), check=True, capture_output=True)
d = time() - t
return len(p.stdout), d


def main(args):
filename = args.image
quality = args.quality

result = {
"image": filename,
"quality": quality,
"effort": [],
"plugin_size": [],
"plugin_time": [],
"refenc_size": [],
"refenc_time": [],
}
print("Quality:", quality)
for effort in range(1, 10):
size_plugin, time_plugin = encode_plugin(filename, quality, effort)
size_refenc, time_refenc = encode_cli(filename, quality, effort)
print(f"\nEffort {effort}")
print(f" plugin [size: {size_plugin}, duration: {time_plugin:.3f}]")
print(f" reference [size: {size_refenc}, duration: {time_refenc:.3f}]")

result["effort"].append(effort)
result["plugin_size"].append(size_plugin)
result["plugin_time"].append(time_plugin)
result["refenc_size"].append(size_refenc)
result["refenc_time"].append(time_refenc)

if args.output_json:
with open(args.output_json, "w") as f:
json.dump(result, f, indent=4)


if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("-i", "--image", help="Image file for encode benchmark", required=True)
parser.add_argument("-q", "--quality", type=int, default=98, help="Quality level")
parser.add_argument("-o", "--output-json", help="Output JSON file")
args = parser.parse_args()
main(args)
Binary file added test/images/bench.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit e676784

Please sign in to comment.