Skip to content

Benchmark

Benchmark #71

Workflow file for this run

name: Benchmark
on:
schedule:
- cron: '0 0 * * *' # Daily at midnight UTC
workflow_dispatch:
inputs:
iterations:
description: 'Iterations per provider'
required: false
default: '100'
concurrency:
description: 'Concurrent sandboxes for burst/staggered tests'
required: false
default: '100'
mode:
description: 'Test mode (leave empty to run all)'
required: false
default: ''
type: choice
options:
- ''
- sequential
- staggered
- burst
concurrency:
group: benchmarks
cancel-in-progress: true
permissions:
contents: write
jobs:
bench:
name: Bench ${{ matrix.provider }}
runs-on: namespace-profile-default
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
provider:
- e2b
- daytona
- blaxel
- just-bash
- modal
- vercel
- hopx
- codesandbox
- runloop
- namespace
- cloudflare
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: 'npm'
- run: npm ci
- name: Clear stale results from checkout
run: rm -rf results/
- name: Run benchmark
env:
COMPUTESDK_API_KEY: ${{ secrets.COMPUTESDK_API_KEY }}
E2B_API_KEY: ${{ secrets.E2B_API_KEY }}
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_TEAM_ID: ${{ secrets.VERCEL_TEAM_ID }}
VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }}
BL_API_KEY: ${{ secrets.BL_API_KEY }}
BL_WORKSPACE: ${{ secrets.BL_WORKSPACE }}
MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
DAYTONA_API_KEY: ${{ secrets.DAYTONA_API_KEY }}
NSC_TOKEN: ${{ secrets.NSC_TOKEN }}
HOPX_API_KEY: ${{ secrets.HOPX_API_KEY }}
CSB_API_KEY: ${{ secrets.CSB_API_KEY }}
RUNLOOP_API_KEY: ${{ secrets.RUNLOOP_API_KEY }}
CLOUDFLARE_SANDBOX_URL: ${{ secrets.CLOUDFLARE_SANDBOX_URL }}
CLOUDFLARE_SANDBOX_SECRET: ${{ secrets.CLOUDFLARE_SANDBOX_SECRET }}
run: |
MODE_FLAG=""
if [ -n "${{ github.event.inputs.mode }}" ]; then
MODE_FLAG="--mode ${{ github.event.inputs.mode }}"
fi
npm run bench -- \
--provider ${{ matrix.provider }} \
--iterations ${{ github.event.inputs.iterations || '100' }} \
--concurrency ${{ github.event.inputs.concurrency || '100' }} \
$MODE_FLAG
- name: Upload results
if: always()
uses: actions/upload-artifact@v4
with:
name: results-${{ matrix.provider }}
path: results/
if-no-files-found: ignore
retention-days: 7
collect:
name: Collect Results
runs-on: namespace-profile-default
needs: bench
if: always()
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: 'npm'
- run: npm ci
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
path: artifacts/
pattern: results-*
- name: Merge results
run: npx tsx src/merge-results.ts --input artifacts
- run: npm run generate-svg
- run: npm run generate-pricing-svg
- name: Commit and push
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add results.svg *_tti.svg pricing.svg results/
git diff --cached --quiet && echo "No changes to commit" && exit 0
git commit -m "chore: update benchmark results [skip ci]"
git push