Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions .github/benchmark-config/drivers.json

This file was deleted.

3 changes: 0 additions & 3 deletions .github/benchmark-config/workloads.json

This file was deleted.

228 changes: 226 additions & 2 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,21 @@ name: Benchmark

on:
workflow_dispatch:
inputs:
engines:
description: 'Which engine benchmarks to run'
type: choice
default: all
options:
- all
- java
- ruby
- node
- php

jobs:
benchmark-java:
if: ${{ inputs.engines == 'all' || inputs.engines == 'java' }}
runs-on: ubuntu-latest

strategy:
Expand Down Expand Up @@ -85,6 +97,7 @@ jobs:
retention-days: 30

benchmark-ruby:
if: ${{ inputs.engines == 'all' || inputs.engines == 'ruby' }}
runs-on: ubuntu-latest

strategy:
Expand Down Expand Up @@ -152,8 +165,202 @@ jobs:
path: ${{ steps.names.outputs.result_file }}
retention-days: 30

test-php:
# Fast, server-free PHP engine tests. Uses the recording driver, so it needs
# neither the valkey_glide extension nor a running server.
if: ${{ inputs.engines == 'all' || inputs.engines == 'php' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: json, pcntl
tools: composer

- name: Install PHP dependencies
run: cd php && composer install --no-interaction --prefer-dist

- name: Run PHP unit tests
run: cd php && vendor/bin/phpunit --testsuite unit

- name: Run PHP integration tests (server-free)
run: cd php && vendor/bin/phpunit --testsuite integration

benchmark-php:
if: ${{ inputs.engines == 'all' || inputs.engines == 'php' }}
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
driver:
- configs/drivers/default/valkey-glide-php.json
workload:
- configs/workloads/reference/basic-standalone-single-client-1M-reqs.json

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Set up PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.3'
extensions: json, pcntl, bcmath
tools: composer

- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential php-dev pkg-config \
libssl-dev libffi-dev libprotobuf-c-dev protobuf-c-compiler unzip

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable

- name: Install cbindgen
run: cargo install cbindgen

- name: Build & install valkey_glide extension
run: |
# Build the Valkey GLIDE PHP extension from the upstream repo.
git clone --recurse-submodules https://github.com/valkey-io/valkey-glide-php.git /tmp/vg-php
cd /tmp/vg-php
python3 utils/patch_proto_and_rust.py
(cd valkey-glide/ffi && cargo build --release)
phpize
./configure --enable-valkey-glide
make build-modules-pre
make -j"$(nproc)"
sudo make install
echo "extension=valkey_glide" | sudo tee -a "$(php -i | grep '^Loaded Configuration File' | awk '{print $NF}')"
php -m | grep valkey_glide

- name: Install PHP dependencies
run: cd php && composer install --no-interaction --prefer-dist --optimize-autoloader

- name: Start Valkey server
run: |
make server-standalone-start
sleep 2
work/valkey/bin/valkey-cli ping
work/valkey/bin/valkey-cli CONFIG GET save

- name: Extract names for result file
id: names
run: |
DRIVER_NAME=$(basename ${{ matrix.driver }} .json)
WORKLOAD_NAME=$(basename ${{ matrix.workload }} .json)
echo "driver_name=$DRIVER_NAME" >> $GITHUB_OUTPUT
echo "workload_name=$WORKLOAD_NAME" >> $GITHUB_OUTPUT
echo "result_file=results/github-runner/reference/${DRIVER_NAME}-${WORKLOAD_NAME}.ndjson" >> $GITHUB_OUTPUT

- name: Run benchmark
run: |
mkdir -p results/github-runner/reference
php php/bin/resp-bench \
--server localhost:6379 \
--driver ${{ matrix.driver }} \
--workload ${{ matrix.workload }} \
--metrics ${{ steps.names.outputs.result_file }} \
--commit-id ${{ github.sha }}

- name: Stop Valkey server
if: always()
run: |
make server-standalone-stop || true

- name: Upload results
uses: actions/upload-artifact@v4
with:
name: benchmark-php-${{ steps.names.outputs.driver_name }}-${{ steps.names.outputs.workload_name }}
path: ${{ steps.names.outputs.result_file }}
retention-days: 30

benchmark-node:
if: ${{ inputs.engines == 'all' || inputs.engines == 'node' }}
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
driver:
- configs/drivers/default/valkey-glide-node.json
- configs/drivers/default/ioredis.json
- configs/drivers/default/iovalkey.json
workload:
- configs/workloads/reference/basic-standalone-single-client-1M-reqs.json

steps:
- uses: actions/checkout@v4

# Node 22 LTS: ioredis 6 and node-redis 6 both require >= 20, and 18 is EOL.
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm
cache-dependency-path: node/package-lock.json

- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential

- name: Start Valkey server
run: |
# Use Makefile target which builds from source and configures with persistence disabled
make server-standalone-start
# Wait for server to be ready
sleep 2
# Verify server is up and persistence is disabled
work/valkey/bin/valkey-cli ping
work/valkey/bin/valkey-cli CONFIG GET save

- name: Build Node.js benchmark
run: cd node && npm ci && npm run build

- name: Extract names for result file
id: names
run: |
DRIVER_NAME=$(basename ${{ matrix.driver }} .json)
WORKLOAD_NAME=$(basename ${{ matrix.workload }} .json)
echo "driver_name=$DRIVER_NAME" >> $GITHUB_OUTPUT
echo "workload_name=$WORKLOAD_NAME" >> $GITHUB_OUTPUT
echo "result_file=results/github-runner/reference/${DRIVER_NAME}-${WORKLOAD_NAME}.ndjson" >> $GITHUB_OUTPUT

- name: Run benchmark
run: |
mkdir -p results/github-runner/reference
node node/dist/src/cli.js \
--server localhost:6379 \
--driver ${{ matrix.driver }} \
--workload ${{ matrix.workload }} \
--metrics ${{ steps.names.outputs.result_file }} \
--commit-id ${{ github.sha }}

- name: Stop Valkey server
if: always()
run: |
make server-standalone-stop || true

- name: Upload results
uses: actions/upload-artifact@v4
with:
name: benchmark-node-${{ steps.names.outputs.driver_name }}-${{ steps.names.outputs.workload_name }}
path: ${{ steps.names.outputs.result_file }}
retention-days: 30

generate-graphs:
needs: [benchmark-java, benchmark-ruby]
needs: [benchmark-java, benchmark-ruby, benchmark-php, benchmark-node]
# A skipped `needs` job would skip this one by default, so an engine-scoped
# run would produce no graphs at all. Individual graph steps are gated on the
# same input instead.
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
permissions:
contents: write
Expand All @@ -169,7 +376,7 @@ jobs:

- name: Install dependencies
run: |
pip install matplotlib numpy
pip install -r scripts/requirements.txt

- name: Download all artifacts
uses: actions/download-artifact@v4
Expand All @@ -185,6 +392,7 @@ jobs:

# TODO - rework with matrix orchistrator
- name: Generate Java graphs - 1 Client
if: ${{ inputs.engines == 'all' || inputs.engines == 'java' }}
run: |
python scripts/generate_graphs.py \
--results "results/github-runner/reference/*-basic-standalone-single-client-1M-reqs.ndjson" \
Expand All @@ -195,6 +403,7 @@ jobs:
--commit-id ${{ github.sha }}

- name: Generate Java graphs - 10 Clients
if: ${{ inputs.engines == 'all' || inputs.engines == 'java' }}
run: |
python scripts/generate_graphs.py \
--results "results/github-runner/reference/*-basic-standalone-10-clients.ndjson" \
Expand All @@ -205,6 +414,7 @@ jobs:
--commit-id ${{ github.sha }}

- name: Generate Java graphs - 100 Clients
if: ${{ inputs.engines == 'all' || inputs.engines == 'java' }}
run: |
python scripts/generate_graphs.py \
--results "results/github-runner/reference/*-basic-standalone-100-clients.ndjson" \
Expand All @@ -216,6 +426,7 @@ jobs:

# Ruby graphs — per concurrency level
- name: Generate Ruby graphs - 1 Client
if: ${{ inputs.engines == 'all' || inputs.engines == 'ruby' }}
run: |
python scripts/generate_graphs.py \
--results "results/github-runner/reference/*-basic-standalone-single-client-1M-reqs.ndjson" \
Expand All @@ -226,6 +437,7 @@ jobs:
--commit-id ${{ github.sha }}

- name: Generate Ruby graphs - 10 Clients
if: ${{ inputs.engines == 'all' || inputs.engines == 'ruby' }}
run: |
python scripts/generate_graphs.py \
--results "results/github-runner/reference/*-basic-standalone-10-clients.ndjson" \
Expand All @@ -236,6 +448,7 @@ jobs:
--commit-id ${{ github.sha }}

- name: Generate Ruby graphs - 100 Clients
if: ${{ inputs.engines == 'all' || inputs.engines == 'ruby' }}
run: |
python scripts/generate_graphs.py \
--results "results/github-runner/reference/*-basic-standalone-100-clients.ndjson" \
Expand All @@ -245,6 +458,17 @@ jobs:
--workload "Ruby - 100 Clients" \
--commit-id ${{ github.sha }}

- name: Generate Node.js graphs - 1 Client
if: ${{ inputs.engines == 'all' || inputs.engines == 'node' }}
run: |
python scripts/generate_graphs.py \
--results "results/github-runner/reference/*-basic-standalone-single-client-1M-reqs.ndjson" \
--output graphs/node/1-client/ \
--phase STEADY \
--language node \
--workload "Node.js - 1 Client" \
--commit-id ${{ github.sha }}

- name: Upload graphs
uses: actions/upload-artifact@v4
with:
Expand Down
Loading