Skip to content

linkdb perf baseline #33

linkdb perf baseline

linkdb perf baseline #33

Workflow file for this run

# ----------------------------------------------------------------------
# .github/workflows/perf.yml
# linkdb performance baseline CI (Tier 3 of 3-tier CI model).
#
# pgbench Stage 1/3 perf baseline check, completely decoupled from
# the push / tag / nightly path. Per spec-1.23 Q8 B-WARN this is
# *not* a blocking gate (GitHub Actions shared runners exhibit
# 10-20% variance unsuitable for blocking thresholds);output is an
# artifact for manual review.
#
# Pre-3-tier this ran on every push as part of ci.yml. The 60s
# pgbench × 2 platforms cost ~2 min wallclock for warn-only signal
# that nobody read on routine PRs, so it moved here.
#
# Author: SqlRush <sqlrush@gmail.com>
#
# Portions Copyright (c) 2026, pgrac contributors
#
# Triggers:
# - workflow_dispatch (manual; macOS perf is opt-in because rule 23
# treats Linux as the clean perf authority)
# - schedule cron Monday 06:00 UTC weekly
#
# Future Stage 6 spec upgrades to blocking gate once self-hosted runner
# / same-run ratio comparison is in place.
# ----------------------------------------------------------------------
name: linkdb perf baseline
on:
schedule:
- cron: '0 6 * * 1'
workflow_dispatch:
inputs:
run_macos_perf:
description: 'Also run noisy macOS perf jobs (Linux remains the authority)'
required: false
type: boolean
default: false
xp_extra_guc:
description: 'xnode-profile: extra GUC lines (spec-6.12 D0 value-gate candidate leg)'
required: false
type: string
default: ''
xp_index_relopt:
description: 'xnode-profile: I-axis PK storage parameter (e.g. cluster_reverse_key=on)'
required: false
type: string
default: ''
xp_pair_init_lease:
description: 'xnode-profile: arm space-affinity lease during pair pgbench init only (1 = on)'
required: false
type: string
default: ''
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
perf-baseline:
name: Stage perf baseline (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: ${{ fromJSON((inputs.run_macos_perf && '["ubuntu-latest","macos-latest"]') || '["ubuntu-latest"]') }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update -y
sudo apt-get install -y --no-install-recommends \
build-essential \
libreadline-dev zlib1g-dev libicu-dev \
liblz4-dev libzstd-dev libssl-dev libxml2-dev \
pkg-config
- name: Install macOS dependencies
if: runner.os == 'macOS'
run: |
brew install readline icu4c lz4 zstd openssl@3 libxml2 pkg-config || true
{
echo "PKG_CONFIG_PATH=$(brew --prefix icu4c)/lib/pkgconfig:$(brew --prefix openssl@3)/lib/pkgconfig:$(brew --prefix lz4)/lib/pkgconfig:$(brew --prefix zstd)/lib/pkgconfig"
echo "LDFLAGS=-L$(brew --prefix readline)/lib -L$(brew --prefix zstd)/lib -L$(brew --prefix lz4)/lib -L$(brew --prefix openssl@3)/lib -L$(brew --prefix icu4c)/lib"
echo "CPPFLAGS=-I$(brew --prefix readline)/include -I$(brew --prefix zstd)/include -I$(brew --prefix lz4)/include -I$(brew --prefix openssl@3)/include -I$(brew --prefix icu4c)/include"
} >> $GITHUB_ENV
- name: Configure (--disable-cluster baseline)
run: |
./configure \
--prefix=$HOME/linkdb-disable-install \
--enable-cassert --enable-debug \
--with-openssl --with-icu --with-lz4 --with-zstd \
--disable-cluster
- name: Build + Install (--disable-cluster baseline)
run: |
if [ "$RUNNER_OS" = "Linux" ]; then
make -j$(getconf _NPROCESSORS_ONLN)
else
make -j$(sysctl -n hw.ncpu)
fi
make install
make distclean
- name: Configure (--enable-cluster candidate)
run: |
./configure \
--prefix=$HOME/linkdb-install \
--enable-cassert --enable-debug \
--with-openssl --with-icu --with-lz4 --with-zstd \
--enable-cluster
- name: Build + Install (--enable-cluster candidate)
run: |
if [ "$RUNNER_OS" = "Linux" ]; then
make -j$(getconf _NPROCESSORS_ONLN)
else
make -j$(sysctl -n hw.ncpu)
fi
make install
- name: Stage off/on pgbench baseline (warn-only)
continue-on-error: true
run: |
PGRAC_ENABLE_INSTALL=$HOME/linkdb-install \
PGRAC_DISABLE_INSTALL=$HOME/linkdb-disable-install \
scripts/perf/run-baseline.sh \
--mode=both \
--scale="${PERF_SCALE:-10}" \
--duration="${PERF_DURATION:-30}" \
--clients="${PERF_CLIENTS:-4}" \
--jobs="${PERF_JOBS:-2}"
# spec-3.23 D0/D1: write-path four-quadrant matrix (gate x writeback x fsync).
# Linux-only clean channel (规则 23: macOS perf is noise, not final). Separates
# the CR-gate tax / writeback benefit / pure structural tax so the ≤10% judgment
# lands on quadrant C, and the spec-3.23 CR-gate hot-path fix can be re-tested
# by one CI run. warn-only (perf is never a hard gate, 规则 20.A).
- name: Write-path four-quadrant matrix (warn-only, Linux)
if: runner.os == 'Linux'
continue-on-error: true
run: |
mkdir -p scripts/perf/results
PGRAC_ENABLE_INSTALL=$HOME/linkdb-install \
PGRAC_DISABLE_INSTALL=$HOME/linkdb-disable-install \
QM_SCALE="${PERF_SCALE:-10}" \
QM_DURATION="${QM_DURATION:-15}" \
QM_REPS="${QM_REPS:-3}" \
QM_CLIENTS="${QM_CLIENTS:-8}" \
QM_JOBS="${QM_JOBS:-4}" \
FSYNC_MATRIX="${FSYNC_MATRIX:-yes}" \
scripts/perf/run-quadrant-matrix.sh \
| tee "scripts/perf/results/quadrant-matrix-${{ github.run_id }}.md"
# spec-5.50 D1: CR read-path profile (SELECT-heavy / long-snapshot /
# parallel-scan). Build-invariant counter deltas + cross-backend
# redundancy (= construct_delta / distinct_cr_keys, NOT distinct_blocks);
# absolute wall is cassert-inflated trend only (perf.yml is all-cassert,
# §15.1). warn-only (perf is never a hard gate, 规则 20.A). Perf tier,
# NOT fast-gate / nightly correctness shard (spec-5.50 Q9 / L91).
- name: CR read-path profile (warn-only, Linux)
if: runner.os == 'Linux'
continue-on-error: true
run: |
mkdir -p scripts/perf/results
INSTALL_PREFIX=$HOME/linkdb-install \
scripts/perf/run-cr-profile.sh --axis all \
--rows "${CR_PROFILE_ROWS:-3000}" \
--readers "${CR_PROFILE_READERS:-4}" \
--out "scripts/perf/results/cr-profile-${{ github.run_id }}.csv" \
| tee "scripts/perf/results/cr-profile-${{ github.run_id }}.log"
# spec-5.20 D6: Hang Manager MG-A false-positive rate + MG-B detection/
# remediation latency (report-only measure-and-decide). FP rate < 1% is a
# tuning reference, NOT a ship bar; the HG#2 zero-unsafe invariant is the
# only hard property (a genuinely-unsafe disposition exits non-zero).
# NO-GO / tuning recommendation is a legitimate latency outcome (spec §3.2).
# warn-only (perf is never a hard gate, 规则 20.A; Tier-3 weekly/manual).
- name: Hang Manager FP-rate + latency (warn-only, Linux)
if: runner.os == 'Linux'
continue-on-error: true
run: |
mkdir -p scripts/perf/results
PGRAC_ENABLE_INSTALL=$HOME/linkdb-install \
PGRAC_RESULTS_DIR=scripts/perf/results \
PGRAC_MG_WINDOW="${MG_WINDOW:-20}" \
scripts/perf/measure-hang-fp-rate.sh || true
PGRAC_ENABLE_INSTALL=$HOME/linkdb-install \
PGRAC_RESULTS_DIR=scripts/perf/results \
scripts/perf/measure-hang-latency.sh || true
# spec-6.0a D7: storage I/O report-only matrix. The default CI leg uses a
# regular-file raw image with O_DIRECT disabled, so it is a conformance and
# trend artifact rather than a hardware O_DIRECT claim.
- name: Storage I/O matrix (warn-only, Linux)
if: runner.os == 'Linux'
continue-on-error: true
run: |
mkdir -p scripts/perf/results
PGRAC_ENABLE_INSTALL=$HOME/linkdb-install \
STORAGE_IO_DURATION="${STORAGE_IO_DURATION:-10}" \
STORAGE_IO_SCALE="${STORAGE_IO_SCALE:-5}" \
scripts/perf/run-storage-io-matrix.sh
- name: Collect perf artifacts
if: always()
run: |
mkdir -p perf-baseline-artifact
cp -R scripts/perf/results perf-baseline-artifact/results 2>/dev/null || true
- name: Upload perf baseline artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: perf-baseline-${{ matrix.os }}-${{ github.run_id }}
path: perf-baseline-artifact/
if-no-files-found: ignore
retention-days: 60
# ----------------------------------------------------------------------
# spec-3.4e D4 — NEW perf-2node-baseline job
#
# 4 workload class via ClusterPair fixture (Perl runner). Per L91
# tier separation, weekly + manual workflow_dispatch only;
# warn-only artifact upload (not blocking).
#
# macOS gets continue-on-error per spec-3.4e F6 (ClusterPair
# stability on macOS runner not yet verified;Linux primary).
# ----------------------------------------------------------------------
perf-2node-baseline:
name: Stage 3.4e 2-node perf baseline (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: ${{ fromJSON((inputs.run_macos_perf && '["ubuntu-latest","macos-latest"]') || '["ubuntu-latest"]') }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
continue-on-error: ${{ matrix.os == 'macos-latest' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update -y
sudo apt-get install -y --no-install-recommends \
build-essential \
libreadline-dev zlib1g-dev libicu-dev \
liblz4-dev libzstd-dev libssl-dev libxml2-dev \
pkg-config libipc-run-perl
- name: Install macOS dependencies
if: runner.os == 'macOS'
run: |
brew install readline icu4c lz4 zstd openssl@3 libxml2 pkg-config || true
sudo cpan -i IPC::Run || true
{
echo "PKG_CONFIG_PATH=$(brew --prefix icu4c)/lib/pkgconfig:$(brew --prefix openssl@3)/lib/pkgconfig:$(brew --prefix lz4)/lib/pkgconfig:$(brew --prefix zstd)/lib/pkgconfig"
echo "LDFLAGS=-L$(brew --prefix readline)/lib -L$(brew --prefix zstd)/lib -L$(brew --prefix lz4)/lib -L$(brew --prefix openssl@3)/lib -L$(brew --prefix icu4c)/lib"
echo "CPPFLAGS=-I$(brew --prefix readline)/include -I$(brew --prefix zstd)/include -I$(brew --prefix lz4)/include -I$(brew --prefix openssl@3)/include -I$(brew --prefix icu4c)/include"
} >> $GITHUB_ENV
- name: Configure (--enable-cluster + --enable-injection-points)
run: |
./configure \
--prefix=$HOME/linkdb-install \
--enable-cassert --enable-debug \
--enable-injection-points --enable-tap-tests \
--with-openssl --with-icu --with-lz4 --with-zstd \
--enable-cluster
- name: Build + Install
run: |
if [ "$RUNNER_OS" = "Linux" ]; then
make -j$(getconf _NPROCESSORS_ONLN)
else
make -j$(sysctl -n hw.ncpu)
fi
make install
- name: Run 2-node baseline (5 workload classes — report-only)
run: |
export PGRAC_ENABLE_INSTALL=$HOME/linkdb-install
export PATH=$HOME/linkdb-install/bin:$PATH
# PGRAC: PG TAP framework needs port-reservation directory + pg_regress
# path for ClusterPair --config-auth (spec-3.4e Hardening v1.0.1 fix —
# ubuntu-latest 1st run silently no-op'd class 2/3/4 without these).
mkdir -p /tmp/pgrac-portlock
export PG_TEST_PORT_DIR=/tmp/pgrac-portlock
export PG_REGRESS="$(pwd)/src/test/regress/pg_regress"
# class 2/3/4 via Perl runner (ClusterPair fixture);
# class 1 (single-node-no-peer) covered by existing perf-baseline job above.
status=0
for class in 2node-local-affinity 2node-cross-node-visibility 2node-hot-row-lock 2node-subxact-nesting 2node-multixact-shared-lock; do
echo "=== Running $class ==="
rm -rf tmp_check # avoid "File exists" Bail between classes
if scripts/perf/run-2node-baseline.sh \
--mode="$class" \
--scale="${PERF_SCALE:-10}" \
--duration="${PERF_DURATION:-30}" \
--clients="${PERF_CLIENTS:-4}" \
--jobs="${PERF_JOBS:-2}"; then
artifact=$(find scripts/perf/results -maxdepth 1 -name "3-4e-${class}-*.json" -print -quit)
if [ -n "$artifact" ]; then
echo "report artifact: $artifact"
else
echo "::warning::2-node perf class $class finished without a JSON artifact"
status=1
fi
else
echo "::warning::2-node perf class $class failed; continuing because perf is report-only"
status=1
fi
done
if [ "$status" -ne 0 ]; then
{
echo "### 2-node perf baseline report-only failures"
echo
echo "One or more 2-node perf classes failed or missed an artifact."
echo "Build/configure failures still fail this workflow; pgbench perf legs are warning-only."
} >> "$GITHUB_STEP_SUMMARY"
fi
exit 0
- name: Collect 2-node perf artifacts
if: always()
run: |
mkdir -p perf-2node-artifact
cp -R scripts/perf/results perf-2node-artifact/results 2>/dev/null || true
# PGRAC: also upload PG TAP framework regress logs for diagnostics
# (Perl runner redirects STDOUT/STDERR there; without these, CI silent
# failures are invisible).
cp -R log perf-2node-artifact/log 2>/dev/null || true
- name: Upload 2-node perf artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: perf-2node-baseline-${{ matrix.os }}-${{ github.run_id }}
path: perf-2node-artifact/
if-no-files-found: ignore
retention-days: 60
perf-stage4-recovery:
name: Stage 4 recovery + write-fence perf baseline (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: ${{ fromJSON((inputs.run_macos_perf && '["ubuntu-latest","macos-latest"]') || '["ubuntu-latest"]') }}
runs-on: ${{ matrix.os }}
timeout-minutes: 60
continue-on-error: ${{ matrix.os == 'macos-latest' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update -y
sudo apt-get install -y --no-install-recommends \
build-essential \
libreadline-dev zlib1g-dev libicu-dev \
liblz4-dev libzstd-dev libssl-dev libxml2-dev \
pkg-config libipc-run-perl
- name: Install macOS dependencies
if: runner.os == 'macOS'
run: |
brew install readline icu4c lz4 zstd openssl@3 libxml2 pkg-config || true
sudo cpan -i IPC::Run || true
{
echo "PKG_CONFIG_PATH=$(brew --prefix icu4c)/lib/pkgconfig:$(brew --prefix openssl@3)/lib/pkgconfig:$(brew --prefix lz4)/lib/pkgconfig:$(brew --prefix zstd)/lib/pkgconfig"
echo "LDFLAGS=-L$(brew --prefix readline)/lib -L$(brew --prefix zstd)/lib -L$(brew --prefix lz4)/lib -L$(brew --prefix openssl@3)/lib -L$(brew --prefix icu4c)/lib"
echo "CPPFLAGS=-I$(brew --prefix readline)/include -I$(brew --prefix zstd)/include -I$(brew --prefix lz4)/include -I$(brew --prefix openssl@3)/include -I$(brew --prefix icu4c)/include"
} >> $GITHUB_ENV
# spec-4.13 D0 clean-run contract: NON-cassert release builds (cassert is
# ~40% noise; closure-grade numbers require a release build). --enable-tap-
# tests provides pg_regress + the PG TAP framework the Perl runners use; it
# does not add cassert (the postgres binary stays release).
- name: Configure + Build --disable-cluster (release baseline)
run: |
./configure \
--prefix=$HOME/linkdb-disable-install \
--enable-tap-tests \
--with-openssl --with-icu --with-lz4 --with-zstd \
--disable-cluster
if [ "$RUNNER_OS" = "Linux" ]; then
make -j$(getconf _NPROCESSORS_ONLN)
else
make -j$(sysctl -n hw.ncpu)
fi
make install
make distclean
- name: Configure + Build --enable-cluster (release candidate)
run: |
./configure \
--prefix=$HOME/linkdb-install \
--enable-tap-tests \
--with-openssl --with-icu --with-lz4 --with-zstd \
--enable-cluster
if [ "$RUNNER_OS" = "Linux" ]; then
make -j$(getconf _NPROCESSORS_ONLN)
else
make -j$(sysctl -n hw.ncpu)
fi
make install
- name: Run Stage 4 recovery baseline (--nodes=2 --bands=all, report-only)
run: |
export PGRAC_ENABLE_INSTALL=$HOME/linkdb-install
export PGRAC_DISABLE_INSTALL=$HOME/linkdb-disable-install
export PATH=$HOME/linkdb-install/bin:$PATH
# PG TAP framework needs the port-reservation dir + pg_regress path for
# ClusterPair / PgracClusterNode (mirrors the 2-node baseline job).
mkdir -p /tmp/pgrac-portlock
export PG_TEST_PORT_DIR=/tmp/pgrac-portlock
export PG_REGRESS="$(pwd)/src/test/regress/pg_regress"
# ABSOLUTE TESTDATADIR so PostgreSQL::Test::Utils::tempdir() yields
# absolute paths -- ClusterPair's quorum voting-disk files are opened by
# the postmaster (a different cwd), so a relative path FATALs at boot
# ("cluster.voting_disks: cannot open tmp_check/.../disk0").
export TESTDATADIR="$(pwd)/tmp_check"
rm -rf tmp_check
# Single-node bands + delegated 2-node steady (P0-1/P0-2) + block
# recovery latency (P0-5/6/7). report-only (perf is never a hard gate,
# 规则 20.A); a 2-node leg that cannot sustain a clean OLTP workload is
# honestly recorded as UNAVAILABLE in the JSON, not faked.
scripts/perf/run-stage4-recovery-baseline.sh \
--tier="${PERF_TIER:-smoke}" \
--bands=all \
--nodes=2 \
--scale="${PERF_SCALE:-10}" \
--duration="${PERF_DURATION:-30}" \
|| echo "::warning::stage4 perf driver exited non-zero (report-only)"
exit 0
- name: Collect Stage 4 perf artifacts
if: always()
run: |
mkdir -p perf-stage4-artifact
cp -R scripts/perf/results perf-stage4-artifact/results 2>/dev/null || true
cp -R log perf-stage4-artifact/log 2>/dev/null || true
- name: Upload Stage 4 perf artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: perf-stage4-recovery-${{ matrix.os }}-${{ github.run_id }}
path: perf-stage4-artifact/
if-no-files-found: ignore
retention-days: 60
# spec-5.59 D8: cross-node four-axis profiling (write / read / index /
# commit-SCN) on the clean Linux runner. Own job with a NON-cassert
# -O2 build: cassert memory checking pollutes per-bucket nanoseconds
# (the spec-5.19 writetax-profile lesson), and the pp attribution needs
# honest requester-wait timings. Warn-only artifact (L91 / rule 20.A:
# perf tiers never block); deterministic counters (reship rate, bucket
# n_events) are the primary signal, TPS medians are trend-only.
xnode-profile:
name: Cross-node four-axis profile (Linux, warn-only)
runs-on: ubuntu-latest
timeout-minutes: 45
continue-on-error: true
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Linux dependencies
run: |
sudo apt-get update -y
sudo apt-get install -y --no-install-recommends \
build-essential \
libreadline-dev zlib1g-dev libicu-dev \
liblz4-dev libzstd-dev libssl-dev libxml2-dev \
pkg-config libipc-run-perl
- name: Configure (--enable-cluster, non-cassert -O2)
run: |
./configure \
--prefix=$HOME/linkdb-install \
--enable-tap-tests \
CFLAGS="-O2 -fno-omit-frame-pointer -g" \
--with-openssl --with-icu --with-lz4 --with-zstd \
--enable-cluster
- name: Build + Install
run: |
make -j$(getconf _NPROCESSORS_ONLN)
make install
- name: Run four-axis xnode profile (warn-only)
continue-on-error: true
run: |
mkdir -p scripts/perf/results
XP_INSTALL=$HOME/linkdb-install \
XP_SECS="${XP_SECS:-8}" \
XP_ROUNDS="${XP_ROUNDS:-5}" \
XP_SCALE="${XP_SCALE:-10}" \
XP_EXTRA_GUC="${{ inputs.xp_extra_guc }}" \
XP_INDEX_RELOPT="${{ inputs.xp_index_relopt }}" \
XP_PAIR_INIT_LEASE="${{ inputs.xp_pair_init_lease }}" \
XP_TSV_OUT="scripts/perf/results/xnode-profile-${{ github.run_id }}.tsv" \
XP_OUT="scripts/perf/results/xnode-profile-${{ github.run_id }}.md" \
perl scripts/perf/run_2node_xnode_profile.pl \
| tee "scripts/perf/results/xnode-profile-${{ github.run_id }}.log"
- name: Upload xnode profile artifact
if: always()
uses: actions/upload-artifact@v4
with:
name: xnode-profile-${{ github.run_id }}
path: scripts/perf/results/
if-no-files-found: ignore
retention-days: 90