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
38 changes: 38 additions & 0 deletions .github/actions/tests/run-benchmark-tests/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: 'Run Benchmark Tests'
description: 'Run Playwright benchmark tests and compare against baseline'
inputs:
os:
description: 'Operating system (ubuntu, macos, windows)'
default: 'ubuntu'
update-baseline:
description: 'Update baseline instead of comparing'
default: 'false'
runs:
using: 'composite'
steps:
- name: Run Benchmark Tests (Ubuntu)
if: inputs.os == 'ubuntu'
shell: bash
run: xvfb-run npm run test:benchmark

- name: Run Benchmark Tests
if: inputs.os != 'ubuntu'
shell: bash
run: npm run test:benchmark

- name: Update Baseline
if: inputs.update-baseline == 'true'
shell: bash
run: >-
node tests/benchmarks/utils/compare.js
--results tests/benchmarks/results/mounting.json
--baseline tests/benchmarks/mounting/baseline.${{ inputs.os }}.json
--update-baseline

- name: Compare Against Baseline
if: inputs.update-baseline != 'true'
shell: bash
run: >-
node tests/benchmarks/utils/compare.js
--results tests/benchmarks/results/mounting.json
--baseline tests/benchmarks/mounting/baseline.${{ inputs.os }}.json
88 changes: 88 additions & 0 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
name: Benchmarks
on:
workflow_dispatch:
inputs:
update-baseline:
description: 'Update baseline with current results instead of comparing'
type: boolean
default: false
pull_request:
branches: [main, 'release/v*']

jobs:
benchmark:
name: Performance Benchmarks (${{ matrix.os }})
timeout-minutes: 60
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-24.04, macos-latest, windows-latest]
include:
- os: ubuntu-24.04
os-name: ubuntu
- os: macos-latest
os-name: macos
- os: windows-latest
os-name: windows
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v6

- name: Install System Dependencies (Ubuntu)
if: matrix.os-name == 'ubuntu'
run: |
sudo apt-get update
sudo apt-get --no-install-recommends install -y \
libglib2.0-0 libnss3 libdbus-1-3 libatk1.0-0 libatk-bridge2.0-0 libcups2 libgtk-3-0 libasound2t64 \
xvfb

- name: Setup Node Dependencies
uses: ./.github/actions/common/setup-node-deps

- name: Configure Chrome Sandbox
if: matrix.os-name == 'ubuntu'
run: |
sudo chown root node_modules/electron/dist/chrome-sandbox
sudo chmod 4755 node_modules/electron/dist/chrome-sandbox

- name: Run Benchmark Tests
uses: ./.github/actions/tests/run-benchmark-tests
with:
os: ${{ matrix.os-name }}
update-baseline: ${{ github.event.inputs.update-baseline || 'false' }}

- name: Upload Benchmark Results
uses: actions/upload-artifact@v6
if: ${{ !cancelled() }}
with:
name: benchmark-results-${{ matrix.os-name }}
path: |
tests/benchmarks/results/
benchmark-report/
retention-days: 30

- name: Commit Updated Baseline
if: github.event.inputs.update-baseline == 'true'
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add tests/benchmarks/mounting/baseline.${{ matrix.os-name }}.json
git diff --staged --quiet || git commit -m "chore: update ${{ matrix.os-name }} benchmark baseline" && git push
Comment thread
sid-bruno marked this conversation as resolved.

- name: Comment Benchmark Results on PR
if: github.event_name == 'pull_request' && !cancelled()
continue-on-error: true
uses: actions/github-script@v7
with:
script: |
const run = require('./tests/benchmarks/utils/pr-comment.js');
await run({
github,
context,
resultsPath: 'tests/benchmarks/results/mounting.json',
baselinePath: 'tests/benchmarks/mounting/baseline.${{ matrix.os-name }}.json',
title: 'Benchmark Results — Collection Mount (${{ matrix.os-name }})'
});
Comment thread
coderabbitai[bot] marked this conversation as resolved.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ skills-lock.json
# Playwright
/blob-report/

# Benchmark results (generated at runtime)
tests/benchmarks/results/
/benchmark-report/

# Development plan files
CLAUDE.md
AGENTS.md
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"test:e2e": "playwright test --project=default",
"test:e2e:ssl": "playwright test --project=ssl",
"test:e2e:auth": "playwright test --project=auth",
"test:benchmark": "playwright test --config=playwright.benchmark.config.ts",
"lint": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" npx eslint",
"lint:fix": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" npx eslint --fix",
"prepare": "husky"
Expand Down
38 changes: 38 additions & 0 deletions playwright.benchmark.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { defineConfig } from '@playwright/test';

export default defineConfig({
fullyParallel: false,
forbidOnly: !!process.env.CI,
retries: 0,
workers: 1,
reporter: [
['list'],
['json', { outputFile: 'benchmark-report/results.json' }]
],

use: {
trace: 'off'
},

projects: [
{
name: 'benchmarks',
testDir: './tests/benchmarks',
testMatch: '**/*.bench.ts'
}
],

webServer: [
{
command: 'npm run dev:web',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
timeout: 10 * 60 * 1000
}
],

timeout: 10 * 60 * 1000,
expect: {
timeout: 120_000
}
});
3 changes: 2 additions & 1 deletion playwright.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export default defineConfig({
testDir: './tests',
testIgnore: [
'ssl/**', // custom CA certificate tests require separate server setup and certificate generation
'auth/**' // auth tests have their own project
'auth/**', // auth tests have their own project
'benchmarks/**'
]
},
{
Expand Down
45 changes: 45 additions & 0 deletions tests/benchmarks/mounting/baseline.macos.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"thresholdPercent": 20,
"entries": {
"bru-50": {
"mean": 2200,
"p50": 1000
},
"bru-200": {
"mean": 1300,
"p50": 1100
},
"bru-500": {
"mean": 3600,
"p50": 3500
},
"bru-1000": {
"mean": 9100,
"p50": 9000
},
"bru-3000": {
"mean": 185000,
"p50": 183000
},
"yml-50": {
"mean": 700,
"p50": 650
},
"yml-200": {
"mean": 1400,
"p50": 1250
},
"yml-500": {
"mean": 3900,
"p50": 3700
},
"yml-1000": {
"mean": 11700,
"p50": 11900
},
"yml-3000": {
"mean": 85000,
"p50": 80000
}
}
}
45 changes: 45 additions & 0 deletions tests/benchmarks/mounting/baseline.ubuntu.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"thresholdPercent": 20,
"entries": {
"bru-50": {
"mean": 1500,
"p50": 700
},
"bru-200": {
"mean": 1200,
"p50": 1150
},
"bru-500": {
"mean": 2900,
"p50": 2900
},
"bru-1000": {
"mean": 8000,
"p50": 8000
},
"bru-3000": {
"mean": 175000,
"p50": 170000
},
"yml-50": {
"mean": 600,
"p50": 560
},
"yml-200": {
"mean": 1200,
"p50": 1200
},
"yml-500": {
"mean": 3500,
"p50": 3400
},
"yml-1000": {
"mean": 10700,
"p50": 10650
},
"yml-3000": {
"mean": 85000,
"p50": 80000
}
}
}
45 changes: 45 additions & 0 deletions tests/benchmarks/mounting/baseline.windows.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"thresholdPercent": 20,
"entries": {
"bru-50": {
"mean": 2700,
"p50": 800
},
"bru-200": {
"mean": 1500,
"p50": 1400
},
"bru-500": {
"mean": 3500,
"p50": 3500
},
"bru-1000": {
"mean": 9500,
"p50": 9400
},
"bru-3000": {
"mean": 195000,
"p50": 190000
},
"yml-50": {
"mean": 600,
"p50": 570
},
"yml-200": {
"mean": 1350,
"p50": 1300
},
"yml-500": {
"mean": 3800,
"p50": 3700
},
"yml-1000": {
"mean": 11000,
"p50": 11000
},
"yml-3000": {
"mean": 90000,
"p50": 88000
}
Comment thread
sid-bruno marked this conversation as resolved.
}
}
Loading
Loading