Skip to content

Commit 3abc303

Browse files
authored
[ci] add router benchmark script and CI (#7498)
1 parent afeed46 commit 3abc303

File tree

9 files changed

+1461
-0
lines changed

9 files changed

+1461
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
name: PR Benchmark (Rust Router)
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
paths:
7+
- "sgl-router/**"
8+
pull_request:
9+
branches: [ main ]
10+
paths:
11+
- "sgl-router/**"
12+
workflow_dispatch:
13+
14+
concurrency:
15+
group: pr-benchmark-rust-${{ github.ref }}
16+
cancel-in-progress: true
17+
permissions:
18+
contents: read
19+
pull-requests: write
20+
issues: write
21+
jobs:
22+
benchmark-router:
23+
if: github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request'
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Checkout code
27+
uses: actions/checkout@v4
28+
with:
29+
# Fetch enough history for baseline comparison
30+
fetch-depth: 100
31+
32+
- name: Install dependencies
33+
run: |
34+
bash scripts/ci_install_rust.sh
35+
36+
- name: Cache Rust dependencies
37+
uses: actions/cache@v4
38+
with:
39+
path: |
40+
~/.cargo/bin/
41+
~/.cargo/registry/index/
42+
~/.cargo/registry/cache/
43+
~/.cargo/git/db/
44+
sgl-router/target/
45+
key: ${{ runner.os }}-cargo-${{ hashFiles('sgl-router/Cargo.lock') }}
46+
restore-keys: |
47+
${{ runner.os }}-cargo-
48+
49+
- name: Build router in release mode
50+
run: |
51+
source "$HOME/.cargo/env"
52+
cd sgl-router/
53+
cargo build --release
54+
55+
- name: Run quick benchmarks
56+
timeout-minutes: 15
57+
run: |
58+
source "$HOME/.cargo/env"
59+
cd sgl-router/
60+
# Run quick benchmarks for PR validation using Python script
61+
python3 scripts/run_benchmarks.py --quick --validate-thresholds --save-results
62+
63+
- name: Upload benchmark results
64+
if: always()
65+
uses: actions/upload-artifact@v4
66+
with:
67+
name: benchmark-results-${{ github.sha }}
68+
path: |
69+
sgl-router/target/criterion/
70+
retention-days: 30
71+
72+
- name: Post benchmark results as PR comment
73+
if: github.event_name == 'pull_request'
74+
run: |
75+
cd sgl-router/
76+
# Use Python script to post benchmark comment
77+
python3 scripts/post_benchmark_comment.py \
78+
--pr-number ${{ github.event.number }} \
79+
--commit-sha ${{ github.sha }} \
80+
--results-file benchmark_results.env
81+
env:
82+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
83+
84+
benchmark-integration-test:
85+
if: github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request'
86+
runs-on: ubuntu-latest
87+
steps:
88+
- name: Checkout code
89+
uses: actions/checkout@v4
90+
91+
- name: Install dependencies
92+
run: |
93+
bash scripts/ci_install_rust.sh
94+
95+
- name: Cache Rust dependencies
96+
uses: actions/cache@v4
97+
with:
98+
path: |
99+
~/.cargo/bin/
100+
~/.cargo/registry/index/
101+
~/.cargo/registry/cache/
102+
~/.cargo/git/db/
103+
sgl-router/target/
104+
key: ${{ runner.os }}-cargo-${{ hashFiles('sgl-router/Cargo.lock') }}
105+
restore-keys: |
106+
${{ runner.os }}-cargo-
107+
108+
- name: Run benchmark integration tests
109+
timeout-minutes: 10
110+
run: |
111+
source "$HOME/.cargo/env"
112+
cd sgl-router/
113+
# Run integration tests to ensure benchmark code compiles and works
114+
cargo test --test benchmark_integration
115+
116+
- name: Verify benchmark compilation
117+
run: |
118+
source "$HOME/.cargo/env"
119+
cd sgl-router/
120+
# Ensure all benchmarks compile without running them
121+
cargo check --benches

.github/workflows/pr-test-rust.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,20 @@ jobs:
4040
cd sgl-router/
4141
cargo test
4242
43+
- name: Check benchmark compilation
44+
run: |
45+
source "$HOME/.cargo/env"
46+
cd sgl-router/
47+
cargo check --benches
48+
49+
- name: Quick benchmark sanity check
50+
timeout-minutes: 10
51+
run: |
52+
source "$HOME/.cargo/env"
53+
cd sgl-router/
54+
# Run quick benchmarks to ensure they work using Python script
55+
python3 scripts/run_benchmarks.py --quick
56+
4357
e2e-python:
4458
if: github.repository == 'sgl-project/sglang' || github.event_name == 'pull_request'
4559
runs-on: 2-gpu-runner

sgl-router/Cargo.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,15 @@ metrics-exporter-prometheus = "0.17.0"
3636
# Added for request tracing
3737
uuid = { version = "1.10", features = ["v4", "serde"] }
3838
thiserror = "2.0.12"
39+
40+
[dev-dependencies]
41+
criterion = { version = "0.5", features = ["html_reports"] }
42+
43+
[[bench]]
44+
name = "request_processing"
45+
harness = false
46+
path = "benches/request_processing.rs"
47+
3948
[profile.release]
4049
lto = "thin"
4150
codegen-units = 1

sgl-router/Makefile

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# SGLang Router Makefile
2+
# Provides convenient shortcuts for common development tasks
3+
4+
.PHONY: help bench bench-quick bench-baseline bench-compare test build clean
5+
6+
help: ## Show this help message
7+
@echo "SGLang Router Development Commands"
8+
@echo "=================================="
9+
@echo ""
10+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}'
11+
@echo ""
12+
13+
build: ## Build the project in release mode
14+
@echo "Building SGLang Router..."
15+
@cargo build --release
16+
17+
test: ## Run all tests
18+
@echo "Running tests..."
19+
@cargo test
20+
21+
bench: ## Run full benchmark suite
22+
@echo "Running full benchmarks..."
23+
@python3 scripts/run_benchmarks.py
24+
25+
bench-quick: ## Run quick benchmarks only
26+
@echo "Running quick benchmarks..."
27+
@python3 scripts/run_benchmarks.py --quick
28+
29+
bench-baseline: ## Save current performance as baseline
30+
@echo "Saving performance baseline..."
31+
@python3 scripts/run_benchmarks.py --save-baseline main
32+
33+
bench-compare: ## Compare with saved baseline
34+
@echo "Comparing with baseline..."
35+
@python3 scripts/run_benchmarks.py --compare-baseline main
36+
37+
bench-ci: ## Run benchmarks suitable for CI (quick mode)
38+
@echo "Running CI benchmarks..."
39+
@python3 scripts/run_benchmarks.py --quick
40+
41+
clean: ## Clean build artifacts
42+
@echo "Cleaning build artifacts..."
43+
@cargo clean
44+
45+
docs: ## Generate and open documentation
46+
@echo "Generating documentation..."
47+
@cargo doc --open
48+
49+
check: ## Run cargo check and clippy
50+
@echo "Running cargo check..."
51+
@cargo check
52+
@echo "Running clippy..."
53+
@cargo clippy
54+
55+
fmt: ## Format code with rustfmt
56+
@echo "Formatting code..."
57+
@cargo fmt
58+
59+
# Development workflow shortcuts
60+
dev-setup: build test ## Set up development environment
61+
@echo "Development environment ready!"
62+
63+
pre-commit: fmt check test bench-quick ## Run pre-commit checks
64+
@echo "Pre-commit checks passed!"
65+
66+
# Benchmark analysis shortcuts
67+
bench-report: ## Open benchmark HTML report
68+
@if [ -f "target/criterion/request_processing/report/index.html" ]; then \
69+
echo "Opening benchmark report..."; \
70+
if command -v xdg-open >/dev/null 2>&1; then \
71+
xdg-open target/criterion/request_processing/report/index.html; \
72+
elif command -v open >/dev/null 2>&1; then \
73+
open target/criterion/request_processing/report/index.html; \
74+
else \
75+
echo "Please open target/criterion/request_processing/report/index.html in your browser"; \
76+
fi \
77+
else \
78+
echo "No benchmark report found. Run 'make bench' first."; \
79+
fi
80+
81+
bench-clean: ## Clean benchmark results
82+
@echo "Cleaning benchmark results..."
83+
@rm -rf target/criterion
84+
85+
# Performance monitoring
86+
perf-monitor: ## Run continuous performance monitoring
87+
@echo "Starting performance monitoring..."
88+
@if command -v watch >/dev/null 2>&1; then \
89+
watch -n 300 'make bench-quick'; \
90+
else \
91+
echo "Warning: 'watch' command not found. Install it or run 'make bench-quick' manually."; \
92+
fi

0 commit comments

Comments
 (0)