Files
sgl-project--sglang/python/sglang/test/performance_test_runner.py
T
wehub-resource-sync 94057c3d3e
PR Test (NPU) / check-changes (push) Has been cancelled
PR Test (NPU) / pr-gate (push) Has been cancelled
PR Test (NPU) / set-image-config (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-1-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (0) (push) Has been cancelled
PR Test (NPU) / stage-b-test-2-npu-a2 (1) (push) Has been cancelled
PR Test (NPU) / stage-b-test-4-npu-a3 (push) Has been cancelled
PR Test (NPU) / stage-b-test-16-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-1-npu-a3 (push) Has been cancelled
PR Test (NPU) / multimodal-gen-test-2-npu-a3 (push) Has been cancelled
PR Test (Arm64) / pr-gate (push) Has been cancelled
PR Test (Arm64) / check-changes (push) Has been cancelled
PR Test (Arm64) / build-test (push) Has been cancelled
PR Test (sgl-router) / gate (push) Has been cancelled
PR Test (sgl-router) / tier-1 — lint (push) Has been cancelled
PR Test (sgl-router) / tier-2 — build + test (push) Has been cancelled
PR Test (sgl-router) / tier-3 — docker (placeholder) (push) Has been cancelled
PR Test (sgl-router) / tier-3 — k8s integration (push) Has been cancelled
PR Test (sgl-router) / tier-3 — e2e (push) Has been cancelled
PR Test (sgl-router) / finish (push) Has been cancelled
PR Test (NPU) / single-node-poc (map[name:qwen3_6_27b_w8a8_1p_in64k_out1k_50ms runner:linux-aarch64-a3-2 test_case:test/registered/ascend/performance/qwen3_6_27b/test_npu_qwen3_6_27b_w8a8_1p_in64k_out1k_50ms.py test_type:perf]) (push) Has been cancelled
PR Test (NPU) / pr-test-npu-finish (push) Has been cancelled
PR Test (Xeon) / pr-gate (push) Has been cancelled
PR Test (Xeon) / check-changes (push) Has been cancelled
PR Test (Xeon) / build-test (, xeon-gnr, base-b-test-cpu) (push) Has been cancelled
PR Test (XPU) / check-changes (push) Has been cancelled
PR Test (XPU) / pr-gate (push) Has been cancelled
PR Test (XPU) / stage-a-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / wait-for-stage-a (push) Has been cancelled
PR Test (XPU) / stage-b-test-1-gpu-xpu (push) Has been cancelled
PR Test (XPU) / finish (push) Has been cancelled
CI Model Inventory / build-inventory (push) Has been cancelled
Lint / lint (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Compilation Check (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Manual Policy (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark - Request Processing (push) Has been cancelled
PR Benchmark (SMG Components) / Benchmark Summary (push) Has been cancelled
PR Test (SMG) / build-wheel (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on windows (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (x86_64 - auto) (push) Has been cancelled
PR Test (SMG) / python-unit-tests (push) Has been cancelled
PR Test (SMG) / unit-tests (push) Has been cancelled
PR Test (SMG) / benchmarks (push) Has been cancelled
PR Test (SMG) / chat-completions (push) Has been cancelled
PR Test (SMG) / chat-completions-4gpu (push) Has been cancelled
PR Test (SMG) / e2e (push) Has been cancelled
PR Test (SMG) / docker-build-test (push) Has been cancelled
PR Test (SMG) / k8s-integration (push) Has been cancelled
PR Test (SMG) / finish (push) Has been cancelled
PR Test (SMG) / summarize-benchmarks (push) Has been cancelled
Release SGLang Model Gateway Docker Image / publish (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on macos (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - auto) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (aarch64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / build on linux (x86_64 - musllinux_1_1) (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Build SDist (push) Has been cancelled
Release SGLang Model Gateway to PyPI / Upload to PyPI (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (aarch64, 12.9, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu129-matrix (x86_64, 12.9, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu129 (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (aarch64, 13.0, 3.10, arm-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / build-cu130-matrix (x86_64, 13.0, 3.10, x64-kernel-build-node) (push) Has been cancelled
Release SGLang Kernels / release-cu130 (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 700) (push) Has been cancelled
Release SGLang Kernels / build-rocm-matrix (3.10, 720) (push) Has been cancelled
Release SGLang Kernels / release-rocm700 (push) Has been cancelled
Release SGLang Kernels / release-rocm720 (push) Has been cancelled
Release SGLang Kernels / build-musa43 (43, 3.10) (push) Has been cancelled
Release SGLang Kernels / release-musa43 (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:38:16 +08:00

248 lines
8.5 KiB
Python

from dataclasses import dataclass, field
from typing import List, Optional, Tuple
from sglang.test.nightly_bench_utils import BenchmarkResult
from sglang.test.nightly_utils import NightlyBenchmarkRunner
from sglang.test.test_utils import DEFAULT_URL_FOR_TEST, ModelLaunchSettings
@dataclass
class PerformanceTestParams:
"""Parameters for performance testing."""
batch_sizes: List[int] = field(default_factory=lambda: [1, 8, 16])
input_lens: Tuple[int, ...] = (8192,)
output_lens: Tuple[int, ...] = (512,)
profile_dir: Optional[str] = None # None = auto-generate based on is_vlm
dataset_name: str = "mmmu" # For VLM perf test
# MTP/EAGLE speculative decoding: minimum accept length threshold (None = no validation)
spec_accept_length_threshold: Optional[float] = None
@dataclass
class PerformanceTestResult:
"""Result of a performance test.
Aggregates metrics across all batch sizes tested for a single model.
"""
model: str
passed: bool
error: Optional[str]
# Aggregate metrics (from the largest batch size result, or None if failed)
latency: Optional[float] = None
input_throughput: Optional[float] = None
output_throughput: Optional[float] = None
overall_throughput: Optional[float] = None
# All individual benchmark results
benchmark_results: Optional[List[BenchmarkResult]] = None
# MTP/EAGLE speculative decoding metric
avg_spec_accept_length: Optional[float] = None
def run_performance_test(
model: ModelLaunchSettings,
perf_runner: NightlyBenchmarkRunner,
batch_sizes: List[int] = None,
input_lens: Tuple[int, ...] = (4096,),
output_lens: Tuple[int, ...] = (512,),
is_vlm: bool = False,
dataset_name: str = "mmmu",
spec_accept_length_threshold: Optional[float] = None,
) -> PerformanceTestResult:
# Set default for mutable argument
if batch_sizes is None:
batch_sizes = [1, 8, 16, 64]
print(f"\n{'='*60}")
print(f"Running PERFORMANCE test for {model.model_path}")
print(f" Variant: {model.variant}")
print(f" Batch sizes: {batch_sizes}")
print(f" Input lens: {input_lens}")
print(f" Output lens: {output_lens}")
if spec_accept_length_threshold is not None:
print(f" Spec accept length threshold: {spec_accept_length_threshold}")
print(f"{'='*60}\n")
# Build extra args for benchmarks
extra_bench_args = ["--trust-remote-code"]
if is_vlm:
extra_bench_args.append(f"--dataset-name={dataset_name}")
try:
results, success, avg_spec_accept_length = perf_runner.run_benchmark_for_model(
model_path=model.model_path,
batch_sizes=batch_sizes,
input_lens=input_lens,
output_lens=output_lens,
other_args=model.extra_args,
variant=model.variant or "",
extra_bench_args=extra_bench_args,
env=model.env,
)
if success and results:
perf_runner.add_report(results, variant=model.variant)
print(f"✓ Performance test succeeded for {model.model_path}")
# The cumulative /server_info accept length is reset by the cache
# flush before the profiling phase, so it can be missing here. Fall
# back to the per-run accept lengths captured during benchmarking.
if avg_spec_accept_length is None:
run_accept_lengths = [
r.acc_length
for r in results
if r.acc_length is not None and r.acc_length > 0
]
if run_accept_lengths:
avg_spec_accept_length = sum(run_accept_lengths) / len(
run_accept_lengths
)
# Validate speculative decoding accept length if threshold is set
error_msg = None
passed = True
if spec_accept_length_threshold is not None:
if avg_spec_accept_length is None:
error_msg = f"Spec accept length threshold set but no accept length reported"
passed = False
print(f"✗ {error_msg}")
elif avg_spec_accept_length < spec_accept_length_threshold:
error_msg = (
f"Spec accept length {avg_spec_accept_length:.2f} < "
f"threshold {spec_accept_length_threshold}"
)
passed = False
print(f"✗ {error_msg}")
else:
print(
f"✓ Spec accept length {avg_spec_accept_length:.2f} >= "
f"threshold {spec_accept_length_threshold}"
)
# Extract aggregate metrics from the largest batch size result
largest_batch_result = max(results, key=lambda r: r.batch_size)
return PerformanceTestResult(
model=model.model_path,
passed=passed,
error=error_msg,
latency=largest_batch_result.latency,
input_throughput=largest_batch_result.input_throughput,
output_throughput=largest_batch_result.output_throughput,
overall_throughput=largest_batch_result.overall_throughput,
benchmark_results=results,
avg_spec_accept_length=avg_spec_accept_length,
)
else:
error_msg = f"Performance test failed for {model.model_path}"
print(f"✗ {error_msg}")
return PerformanceTestResult(
model=model.model_path,
passed=False,
error=error_msg,
)
except Exception as e:
error_msg = f"Performance test exception for {model.model_path}: {str(e)}"
print(f"✗ {error_msg}")
return PerformanceTestResult(
model=model.model_path,
passed=False,
error=error_msg,
)
def run_performance_for_models(
models: List[ModelLaunchSettings],
profile_dir: str,
test_name: str,
base_url: Optional[str] = None,
batch_sizes: List[int] = None,
input_lens: Tuple[int, ...] = (4096,),
output_lens: Tuple[int, ...] = (512,),
is_vlm: bool = False,
dataset_name: str = "mmmu",
) -> dict:
"""Run performance tests for multiple models.
Args:
models: List of ModelLaunchSettings to test
profile_dir: Directory for performance profiles
test_name: Name for the test (used in reports)
base_url: Server base URL (default: DEFAULT_URL_FOR_TEST)
batch_sizes: Batch sizes for perf test
input_lens: Input lengths
output_lens: Output lengths
is_vlm: Whether these are VLM models
dataset_name: Dataset name for VLM benchmarks
Returns:
dict with results:
{
"all_passed": bool,
"results": [PerformanceTestResult, ...]
}
"""
base_url = base_url or DEFAULT_URL_FOR_TEST
# Setup performance runner
perf_runner = NightlyBenchmarkRunner(
profile_dir=profile_dir,
test_name=test_name,
base_url=base_url,
)
perf_runner.setup_profile_directory()
all_results = []
all_passed = True
for model in models:
print("\n" + "=" * 80)
print(f"PERFORMANCE TEST: {model.model_path}")
print(f" TP Size: {model.tp_size}")
print(f" Extra Args: {model.extra_args}")
print("=" * 80)
result = run_performance_test(
model=model,
perf_runner=perf_runner,
batch_sizes=batch_sizes,
input_lens=input_lens,
output_lens=output_lens,
is_vlm=is_vlm,
dataset_name=dataset_name,
)
all_results.append(result)
if not result.passed:
all_passed = False
# Write performance report
perf_runner.write_final_report()
# Print summary
print("\n" + "=" * 60)
print(f"Performance Test Summary: {test_name}")
print("=" * 60)
for result in all_results:
status = "PASS" if result.passed else "FAIL"
throughput_str = (
f", output: {result.output_throughput:.1f} tok/s"
if result.output_throughput
else ""
)
print(f" {result.model}: {status}{throughput_str}")
if result.error:
print(f" Error: {result.error}")
print("\n" + "=" * 60)
print(f"OVERALL: {'ALL PASSED' if all_passed else 'SOME FAILED'}")
print("=" * 60 + "\n")
return {
"all_passed": all_passed,
"results": all_results,
}