Skip to content

Commit a4386ad

Browse files
committed
extra benchmark scripts, slop-generated github workflow, move to profiles folder so we don't trash the project dir
1 parent 69dc618 commit a4386ad

10 files changed

Lines changed: 175 additions & 29 deletions

File tree

.github/workflows/pgo-profile.yaml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Refresh PGO profile
2+
# Regenerates caddy/frankenphp/default.pgo by hammering frankenphp with wrk in
3+
# both regular and worker mode (see build-pgo.sh) and opens a PR with the
4+
# new merged profile. Direct `go build` and the Dockerfile auto-detect it;
5+
# xcaddy users still need an explicit --pgo flag.
6+
concurrency:
7+
cancel-in-progress: false
8+
group: ${{ github.workflow }}-${{ github.ref }}
9+
on:
10+
push:
11+
branches:
12+
- main
13+
paths:
14+
- "**/*.go"
15+
- "frankenphp.c"
16+
- "profiles/**"
17+
- ".github/workflows/pgo-profile.yaml"
18+
workflow_dispatch:
19+
inputs:
20+
bench_seconds:
21+
description: "Seconds to run wrk per script"
22+
default: "30"
23+
required: false
24+
permissions:
25+
contents: write
26+
pull-requests: write
27+
jobs:
28+
refresh:
29+
environment: pgo
30+
name: Generate PGO profile
31+
runs-on: ubuntu-latest
32+
env:
33+
GOTOOLCHAIN: local
34+
GOFLAGS: "-tags=nobadger,nomysql,nopgx"
35+
LIBRARY_PATH: ${{ github.workspace }}/watcher/target/lib
36+
BENCH_SEC: ${{ github.event.inputs.bench_seconds || '30' }}
37+
steps:
38+
- uses: actions/checkout@v6
39+
with:
40+
fetch-depth: 0
41+
# zizmor: ignore[artipacked]
42+
# persist-credentials is intentionally left enabled because this
43+
# workflow needs to push a branch via git push (mirrors translate.yaml).
44+
- uses: actions/setup-go@v6
45+
with:
46+
go-version: "1.26"
47+
cache-dependency-path: |
48+
go.sum
49+
caddy/go.sum
50+
- uses: shivammathur/setup-php@v2
51+
with:
52+
php-version: "8.5"
53+
ini-file: development
54+
coverage: none
55+
tools: none
56+
env:
57+
phpts: ts
58+
debug: true
59+
- name: Install e-dant/watcher
60+
uses: ./.github/actions/watcher
61+
- name: Set CGO flags
62+
run: echo "CGO_CFLAGS=-I${PWD}/watcher/target/include $(php-config --includes)" >> "${GITHUB_ENV}"
63+
- name: Install wrk
64+
run: sudo apt-get update && sudo apt-get install -y wrk
65+
- name: Generate profile
66+
run: ./profiles/build-pgo.sh
67+
- name: Show pprof summary
68+
run: |
69+
go install github.com/google/pprof@latest
70+
"$(go env GOPATH)/bin/pprof" -top -cum -nodecount=25 caddy/frankenphp/default.pgo || true
71+
- name: Open PR with refreshed profile
72+
env:
73+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
74+
ACTOR: ${{ github.actor }}
75+
ACTOR_ID: ${{ github.actor_id }}
76+
RUN_ID: ${{ github.run_id }}
77+
SOURCE_SHA: ${{ github.sha }}
78+
BENCH_SEC: ${{ env.BENCH_SEC }}
79+
run: |
80+
git config user.name "github-actions[bot]"
81+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
82+
BRANCH="pgo/refresh-$RUN_ID"
83+
git checkout -b "$BRANCH"
84+
git add caddy/frankenphp/default.pgo
85+
git diff --cached --quiet && exit 0
86+
git commit -m "perf(pgo): refresh PGO profile" --author="$ACTOR <$ACTOR_ID+$ACTOR@users.noreply.github.com>"
87+
git push origin "$BRANCH"
88+
gh pr create \
89+
--title "perf(pgo): refresh PGO profile" \
90+
--body "Automated refresh of \`caddy/frankenphp/default.pgo\` from \`$SOURCE_SHA\`, generated with \`BENCH_SEC=$BENCH_SEC\` across every script in \`profiles/app/\` in both regular and worker mode." \
91+
--label "perf" \
92+
--label "bot"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/caddy/frankenphp/Build
22
/caddy/frankenphp/Caddyfile.test
33
/caddy/frankenphp/frankenphp
4+
/caddy/frankenphp/frankenphp-pgo
45
/caddy/frankenphp/frankenphp.exe
56
/caddy/frankenphp/public
67
/dist

build-pgo.sh

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

profiles/app/frankenphp_log.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
header('Content-Type: text/plain; charset=utf-8');
3+
4+
if (function_exists('frankenphp_log')) {
5+
frankenphp_log('pgo profile request', FRANKENPHP_LOG_LEVEL_DEBUG, ['s' => 'fp_log']);
6+
frankenphp_log('pgo profile request', FRANKENPHP_LOG_LEVEL_INFO);
7+
} else {
8+
error_log('frankenphp_log unavailable');
9+
}
10+
11+
echo "ok\n";

profiles/app/large_response.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
// trigger encoder middleware in Caddy
3+
header('Content-Type: text/plain; charset=utf-8');
4+
5+
$chunk = str_repeat('Lorem ipsum dolor sit amet, consectetur adipiscing elit. ', 64);
6+
$payload = str_repeat($chunk, 64);
7+
echo $payload;

profiles/app/status_codes.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
$codes = [200, 201, 202, 204, 301, 302, 304, 400, 401, 403, 404, 410, 418, 500, 502, 503];
3+
$code = $codes[mt_rand(0, count($codes) - 1)];
4+
5+
http_response_code($code);
6+
header('Content-Type: text/plain; charset=utf-8');
7+
header('X-Status: ' . $code);
8+
9+
if ($code === 204 || $code === 304) {
10+
return;
11+
}
12+
echo "code=$code\n";

profiles/app/streaming.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
header('Content-Type: text/plain; charset=utf-8');
3+
header('X-Accel-Buffering: no');
4+
5+
while (ob_get_level() > 0) {
6+
ob_end_flush();
7+
}
8+
9+
for ($i = 0; $i < 32; $i++) {
10+
echo "chunk-{$i} ";
11+
echo str_repeat('x', 64);
12+
echo "\n";
13+
flush();
14+
}

benchmark.sh renamed to profiles/benchmark.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
#!/bin/bash
22
set -euo pipefail
33

4-
DIR="$(cd "$(dirname "$0")" && pwd)"
5-
APP="$DIR/profiles/app"
4+
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
5+
APP="$ROOT/profiles/app"
66
MODE=${WORKER:+worker}
77
CADDYFILE="${1:-$APP/Caddyfile.${MODE:-regular}}"
8-
FRANKENPHP_BIN="${FRANKENPHP_BIN:-$DIR/caddy/frankenphp/frankenphp${PGO:+-pgo}}"
8+
FRANKENPHP_BIN="${FRANKENPHP_BIN:-$ROOT/caddy/frankenphp/frankenphp${PGO:+-pgo}}"
99
echo "$FRANKENPHP_BIN"
1010
[ -x "$FRANKENPHP_BIN" ] || {
1111
echo "FRANKENPHP_BIN not executable: $FRANKENPHP_BIN" >&2

profiles/build-pgo.sh

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
# Generate a PGO profile by hammering frankenphp with wrk in both regular and
5+
# worker mode, then merging the two pprof samples into
6+
# caddy/frankenphp/default.pgo. Go auto-detects ./default.pgo in the main
7+
# package, so direct `go build` and the Dockerfile pick it up with no flag changes.
8+
# xcaddy builds in a temp dir and needs
9+
# `--pgo $(go mod download -json github.com/dunglas/frankenphp@latest | jq -r .Dir)/caddy/frankenphp/default.pgo`.
10+
11+
HERE="$(cd "$(dirname "$0")" && pwd)"
12+
ROOT="$(cd "$HERE/.." && pwd)"
13+
export BENCH_SEC=${BENCH_SEC:-8}
14+
N=$(find "$HERE/app" -maxdepth 1 -name "*.php" ! -name "index.php" | wc -l)
15+
TOTAL=$((BENCH_SEC * N))
16+
17+
(cd "$ROOT/caddy/frankenphp" && go build -pgo=off -o frankenphp)
18+
19+
collect() {
20+
"$HERE/benchmark.sh" "$1" >/dev/null &
21+
BPID=$!
22+
until curl -fsS localhost:22019/config/ >/dev/null 2>&1; do sleep 0.2; done
23+
curl -fsS --max-time $((TOTAL + 30)) "localhost:22019/debug/pprof/profile?seconds=$TOTAL" -o "$2"
24+
wait $BPID
25+
}
26+
27+
collect "$HERE/app/Caddyfile.regular" "$HERE/regular.pgo"
28+
collect "$HERE/app/Caddyfile.worker" "$HERE/worker.pgo"
29+
30+
export CGO_CFLAGS="${CGO_CFLAGS:-} -fno-sanitize=undefined"
31+
PPROF="$(go env GOPATH)/bin/pprof"
32+
[ -x "$PPROF" ] || go install github.com/google/pprof@latest
33+
"$PPROF" -proto "$HERE/regular.pgo" "$HERE/worker.pgo" >"$ROOT/caddy/frankenphp/default.pgo"
34+
35+
(cd "$ROOT/caddy/frankenphp" && go build -o frankenphp-pgo)

profiles/merged.pgo

-282 KB
Binary file not shown.

0 commit comments

Comments
 (0)