Skip to content

Commit 7252fa2

Browse files
authored
Merge pull request #25 from LibreSign/chore/remove-unused-quality-gate-script
chore: migrate benchmarks to PHPBench with performance regression guards
2 parents c9e0057 + ad06172 commit 7252fa2

8 files changed

Lines changed: 129 additions & 62 deletions

File tree

.github/copilot-instructions.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,36 @@
99
2. Run focused tests first, then full checks.
1010
3. Ensure performance-sensitive paths stay within benchmark thresholds.
1111

12+
### Running benchmarks
13+
14+
Benchmarks use **PHPBench** for rigorous performance testing with statistical analysis.
15+
16+
```bash
17+
# Run all benchmarks with aggregate statistics
18+
composer benchmark:run
19+
20+
# Run with stricter settings (multiple revisions)
21+
composer benchmark:run:ci
22+
23+
# Update baseline after accepted performance changes
24+
composer benchmark:baseline:update
25+
26+
# Check PR against baseline (native phpbench --ref + --assert)
27+
composer benchmark:baseline:check
28+
29+
# Direct PHPBench invocation with custom options
30+
vendor-bin/phpbench/vendor/phpbench/phpbench/bin/phpbench run --bootstrap=vendor/autoload.php --report=aggregate benchmarks
31+
```
32+
33+
PHPBench automatically:
34+
- Runs warmup iterations (eliminates JIT/opcache startup noise)
35+
- Executes multiple revisions for statistical confidence
36+
- Reports mean, min, max, stdev, variance per benchmark (CI dump file: `build/benchmark-results.xml`)
37+
38+
Baseline persistence policy:
39+
- Regression gate compares PR results against stored `baseline` tag in `.github/.performance/.phpbench`.
40+
- Baseline updates are made via pull request (no direct commit to protected `main`) using `composer benchmark:baseline:update`.
41+
1242
## Compliance and contribution
1343

1444
- DCO sign-off is mandatory for every commit.

.github/workflows/performance.yml

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@ name: performance
55

66
on:
77
pull_request:
8+
push:
9+
branches:
10+
- main
811

912
jobs:
1013
performance:
1114
runs-on: ubuntu-latest
12-
env:
13-
BENCH_ITERATIONS: 250
14-
BENCH_MAX_AVG_MS: 4.0
15-
BENCH_MAX_MEM_KB: 2048
1615
steps:
1716
- uses: actions/checkout@v6
17+
with:
18+
fetch-depth: 0
1819
- name: Detect minimum PHP from composer.json
1920
id: php_min
2021
run: |
@@ -24,5 +25,33 @@ jobs:
2425
- uses: shivammathur/setup-php@v2
2526
with:
2627
php-version: ${{ steps.php_min.outputs.version }}
28+
coverage: none
2729
- run: composer install --no-interaction --prefer-dist
28-
- run: php benchmarks/compiler-benchmark.php
30+
- run: composer bin all install --no-interaction --prefer-dist
31+
32+
- name: Run benchmarks (strict CI mode with verbose output)
33+
run: |
34+
composer benchmark:run:ci
35+
36+
echo "✓ Benchmarks completed"
37+
echo ""
38+
echo "Results saved to build/benchmark-results.xml"
39+
echo "Review: Ensure no individual benchmark takes >10ms average"
40+
41+
- name: Validate regression against baseline
42+
if: github.event_name == 'pull_request'
43+
run: |
44+
if composer benchmark:baseline:exists; then
45+
composer benchmark:baseline:check
46+
else
47+
echo "No 'baseline' tag found in phpbench storage. Skipping baseline comparison."
48+
echo "Run 'composer benchmark:baseline:update' and commit .github/.performance/.phpbench to enable regression gate."
49+
fi
50+
51+
- name: Save benchmark results as artifact
52+
if: always()
53+
uses: actions/upload-artifact@v4
54+
with:
55+
name: benchmark-results
56+
path: build/benchmark-results.xml
57+
retention-days: 90

benchmarks/CompilerBench.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
// SPDX-FileCopyrightText: 2026 LibreSign
4+
// SPDX-License-Identifier: AGPL-3.0-or-later
5+
6+
declare(strict_types=1);
7+
8+
namespace LibreSign\XObjectTemplate\Benchmarks;
9+
10+
use LibreSign\XObjectTemplate\Dto\CompileRequest;
11+
use LibreSign\XObjectTemplate\XObjectTemplateCompiler;
12+
13+
class CompilerBench
14+
{
15+
private ?XObjectTemplateCompiler $compiler = null;
16+
17+
private function compiler(): XObjectTemplateCompiler
18+
{
19+
$this->compiler ??= new XObjectTemplateCompiler();
20+
21+
return $this->compiler;
22+
}
23+
24+
public function benchSimpleHtml(): void
25+
{
26+
$html = '<div style="font-size:10;color:#000">Signed by Demo User</div><p style="font-size:9">Document approved</p>';
27+
$this->compiler()->compile(new CompileRequest(html: $html, width: 240, height: 84));
28+
}
29+
30+
public function benchComplexHtml(): void
31+
{
32+
$html = <<<'HTML'
33+
<div style="font-size:12;font-weight:bold;color:#003366;margin-bottom:10px">
34+
Certificate of Approval
35+
</div>
36+
<p style="font-size:10;line-height:1.5">
37+
This document has been signed by:<br/>
38+
<span style="font-weight:bold">John Doe</span><br/>
39+
Date: 2026-06-01<br/>
40+
Status: <span style="color:green">Verified</span>
41+
</p>
42+
<div style="border:1px solid #ccc;padding:8px;margin-top:10px;font-size:9;background:#f9f9f9">
43+
<p>Signature validated and timestamp recorded.</p>
44+
</div>
45+
HTML;
46+
$this->compiler()->compile(new CompileRequest(html: $html, width: 280, height: 120));
47+
}
48+
}

benchmarks/compiler-benchmark.php

Lines changed: 0 additions & 36 deletions
This file was deleted.

benchmarks/profile.php

Lines changed: 0 additions & 18 deletions
This file was deleted.

composer.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"process-timeout": 600,
3535
"allow-plugins": {
3636
"bamarni/composer-bin-plugin": true,
37-
"infection/extension-installer": true
37+
"infection/extension-installer": true,
38+
"phpbench/extension-installer": true
3839
}
3940
},
4041
"extra": {
@@ -70,12 +71,15 @@
7071
"docker:lint": "docker run --rm -i hadolint/hadolint < .docker/Dockerfile",
7172
"sh:lint": "shfmt -d scripts",
7273
"sh:security": "shellcheck scripts/*.sh",
73-
"profile:xdebug": "XDEBUG_MODE=profile php benchmarks/profile.php",
7474
"test:unit": "vendor-bin/phpunit/vendor/phpunit/phpunit/phpunit --testsuite unit",
7575
"test:integration": "vendor-bin/phpunit/vendor/phpunit/phpunit/phpunit --testsuite integration",
7676
"test:coverage": "XDEBUG_MODE=coverage vendor-bin/phpunit/vendor/phpunit/phpunit/phpunit --coverage-text --coverage-clover=build/coverage/clover.xml",
7777
"mutation:test": "vendor-bin/mutation/vendor/infection/infection/bin/infection --threads=max",
78-
"performance:check": "php benchmarks/compiler-benchmark.php",
78+
"benchmark:run": "vendor-bin/phpbench/vendor/phpbench/phpbench/bin/phpbench run --config=phpbench.json --report=aggregate",
79+
"benchmark:run:ci": "mkdir -p build && vendor-bin/phpbench/vendor/phpbench/phpbench/bin/phpbench run --config=phpbench.json --iterations=20 --revs=10 --warmup=2 --progress=plain --report=aggregate --dump-file=build/benchmark-results.xml",
80+
"benchmark:baseline:update": "mkdir -p build && vendor-bin/phpbench/vendor/phpbench/phpbench/bin/phpbench run --config=phpbench.json --iterations=20 --revs=10 --warmup=2 --progress=plain --report=aggregate --dump-file=build/benchmark-results.xml --store --tag=baseline",
81+
"benchmark:baseline:check": "vendor-bin/phpbench/vendor/phpbench/phpbench/bin/phpbench run --config=phpbench.json --iterations=20 --revs=10 --warmup=2 --progress=plain --report=aggregate --ref=baseline --assert=\"mode(variant.time.avg) <= mode(baseline.time.avg) +/- 25%\"",
82+
"benchmark:baseline:exists": "vendor-bin/phpbench/vendor/phpbench/phpbench/bin/phpbench log --config=phpbench.json | grep -q 'Tag: baseline'",
7983
"bin": [
8084
"composer bin all list"
8185
]

phpbench.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"runner.bootstrap": "vendor/autoload.php",
3+
"runner.path": "benchmarks",
4+
"storage.xml_storage_path": ".github/.performance/.phpbench"
5+
}

vendor-bin/phpbench/composer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"require": {
3+
"phpbench/phpbench": "^1.6"
4+
}
5+
}

0 commit comments

Comments
 (0)