diff --git a/.github/workflows/benchmark.yaml b/.github/workflows/benchmark.yaml new file mode 100644 index 000000000..e02ade938 --- /dev/null +++ b/.github/workflows/benchmark.yaml @@ -0,0 +1,50 @@ +name: Benchmarking PyPDF2 +on: + push: + branches: + - main + pull_request: + branches: [ main ] + +permissions: + contents: write + deployments: write + +jobs: + benchmark: + name: Run pytest-benchmark + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.10"] + steps: + - name: Checkout Code + uses: actions/checkout@v3 + - name: Setup Python + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install requirements (Python 3) + if: matrix.python-version != '2.7' + run: | + pip install -r requirements/ci.txt + - name: Install PyPDF2 + run: | + pip install . + - name: Run benchmark + run: | + pytest Tests/bench.py --benchmark-json output.json + - name: Store benchmark result + uses: benchmark-action/github-action-benchmark@v1 + with: + name: Python Benchmark with pytest-benchmark + tool: 'pytest' + output-file-path: output.json + # Use personal access token instead of GITHUB_TOKEN due to https://github.community/t/github-action-not-triggering-gh-pages-upon-push/16096 + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: true + # Show alert with commit comment on detecting possible performance regression + alert-threshold: '200%' + comment-on-alert: true + fail-on-alert: true + alert-comment-cc-users: '@MartinThoma' \ No newline at end of file diff --git a/Tests/bench.py b/Tests/bench.py new file mode 100644 index 000000000..b74dc56c6 --- /dev/null +++ b/Tests/bench.py @@ -0,0 +1,35 @@ +from PyPDF2 import PdfFileReader +import os + +TESTS_ROOT = os.path.abspath(os.path.dirname(__file__)) +PROJECT_ROOT = os.path.dirname(TESTS_ROOT) +RESOURCE_ROOT = os.path.join(PROJECT_ROOT, "Resources") + + +def page_ops(pdf_path, password): + pdf_path = os.path.join(RESOURCE_ROOT, pdf_path) + + reader = PdfFileReader(pdf_path) + + if password: + reader.decrypt(password) + + page = reader.pages[0] + page.mergeRotatedScaledPage(page, 90, 1, 1) + page.mergeScaledTranslatedPage(page, 1, 1, 1) + page.mergeRotatedScaledTranslatedPage(page, 90, 1, 1, 1, 1) + page.addTransformation([1, 0, 0, 0, 0, 0]) + page.scale(2, 2) + page.scaleBy(0.5) + page.scaleTo(100, 100) + page.compressContentStreams() + page.extractText() + + +def test_page_operations(benchmark): + """ + Apply various page operations. + + Rotation, scaling, translation, content stream compression, text extraction + """ + benchmark(page_ops, "libreoffice-writer-password.pdf", "openpassword") diff --git a/requirements/ci.in b/requirements/ci.in index a7592ecf5..0a6c2f57b 100644 --- a/requirements/ci.in +++ b/requirements/ci.in @@ -3,4 +3,5 @@ flake8 flake8_implicit_str_concat flake8-bugbear pillow -pytest \ No newline at end of file +pytest +pytest-benchmark \ No newline at end of file diff --git a/requirements/ci.txt b/requirements/ci.txt index fcca42ffe..e7e861572 100644 --- a/requirements/ci.txt +++ b/requirements/ci.txt @@ -38,6 +38,8 @@ pluggy==1.0.0 # via pytest py==1.11.0 # via pytest +py-cpuinfo==8.0.0 + # via pytest-benchmark pycodestyle==2.8.0 # via flake8 pyflakes==2.4.0 @@ -45,6 +47,10 @@ pyflakes==2.4.0 pyparsing==3.0.7 # via packaging pytest==7.0.1 + # via + # -r requirements/ci.in + # pytest-benchmark +pytest-benchmark==3.4.1 # via -r requirements/ci.in tomli==1.2.3 # via pytest