Files
2026-07-13 13:22:34 +08:00

113 lines
4.2 KiB
YAML

# Daily benchmark for the MLflow AI Gateway to catch performance regressions.
# Runs against both sqlite (1 instance) and postgres (4 instances + nginx) backends.
#
# THRESHOLD CALIBRATION: The default threshold values below are conservative
# starting points. Run this workflow a few times and tighten thresholds to
# ~2x the observed average. Override per-run via workflow_dispatch inputs.
name: MLflow Gateway Benchmark
on:
schedule:
# Run daily at 06:00 UTC (off-peak; slow-tests runs at 13:00)
- cron: "0 6 * * *"
workflow_dispatch:
inputs:
requests:
description: "Requests per run"
required: false
default: "200"
max_concurrent:
description: "Max concurrent requests (blank = use per-backend default: 10 for both)"
required: false
default: ""
max_p50_ms:
description: "Max P50 latency ms (blank = use per-backend default)"
required: false
default: ""
max_p99_ms:
description: "Max P99 latency ms (blank = use per-backend default)"
required: false
default: ""
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.ref }}
cancel-in-progress: true
defaults:
run:
shell: bash
permissions: {}
jobs:
benchmark:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
if: (github.event_name == 'schedule' && github.repository == 'mlflow/mlflow') || github.event_name == 'workflow_dispatch'
strategy:
fail-fast: false
matrix:
backend: [sqlite, postgres]
include:
- backend: sqlite
instances: 1
default_max_concurrent: 10
default_max_p50_ms: 300
default_max_p99_ms: 800
- backend: postgres
instances: 4
default_max_concurrent: 10
default_max_p50_ms: 400
default_max_p99_ms: 1000
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- uses: ./.github/actions/setup-python
- name: Install dependencies
env:
BACKEND: ${{ matrix.backend }}
run: |
uv sync --extra gateway
if [[ "$BACKEND" == "postgres" ]]; then
uv pip install "psycopg2-binary>=2.9,<3"
fi
- name: Run benchmark (${{ matrix.backend }})
env:
MLFLOW_ENABLE_INCREMENTAL_SPAN_EXPORT: "true"
MLFLOW_USE_BATCH_SPAN_PROCESSOR: "true"
MLFLOW_ENABLE_ASYNC_TRACE_LOGGING: "true"
BACKEND: ${{ matrix.backend }}
INSTANCES: ${{ matrix.instances }}
DEFAULT_MAX_CONCURRENT: ${{ matrix.default_max_concurrent }}
DEFAULT_MAX_P50_MS: ${{ matrix.default_max_p50_ms }}
DEFAULT_MAX_P99_MS: ${{ matrix.default_max_p99_ms }}
REQUESTS: ${{ github.event_name == 'workflow_dispatch' && inputs.requests || '200' }}
MAX_CONCURRENT_OVERRIDE: ${{ github.event_name == 'workflow_dispatch' && inputs.max_concurrent || '' }}
MAX_P50_MS_OVERRIDE: ${{ github.event_name == 'workflow_dispatch' && inputs.max_p50_ms || '' }}
MAX_P99_MS_OVERRIDE: ${{ github.event_name == 'workflow_dispatch' && inputs.max_p99_ms || '' }}
run: |
MAX_CONCURRENT="${MAX_CONCURRENT_OVERRIDE:-$DEFAULT_MAX_CONCURRENT}"
MAX_P50_MS="${MAX_P50_MS_OVERRIDE:-$DEFAULT_MAX_P50_MS}"
MAX_P99_MS="${MAX_P99_MS_OVERRIDE:-$DEFAULT_MAX_P99_MS}"
ARGS=(
--instances "$INSTANCES"
--database "$BACKEND"
--requests "$REQUESTS"
--max-concurrent "$MAX_CONCURRENT"
--max-p50-ms "$MAX_P50_MS"
--max-p99-ms "$MAX_P99_MS"
--runs 3
)
uv run --no-sync dev/benchmarks/gateway/run.py "${ARGS[@]}" \
--output "benchmark-results-$BACKEND.json"
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
if: always()
with:
name: benchmark-results-${{ matrix.backend }}-${{ github.run_id }}
path: benchmark-results-${{ matrix.backend }}.json
retention-days: 30
if-no-files-found: warn