Files
mcp-microsoft/eng/perf-workloads.json

167 lines
7.8 KiB
JSON

{
"catalog_version": "1.0.0",
"description": "Versioned, machine-readable definitions of Azure MCP Server performance workloads and the controlled-environment and statistical rules they run under (issue #3120). Bump catalog_version and record the reason whenever a workload definition changes, since a change can shift baselines.",
"environment_requirements": {
"runner": "Dedicated or sufficiently isolated runner. Baseline-quality runs must not share the host with other CI work; developer laptops are for exploration only.",
"runtime": "The .NET SDK pinned by global.json; record the exact runtime in each result's environment block.",
"build_configuration": "Release.",
"network": "Loopback only for server-overhead workloads. The measured path must exclude Azure and network time (deterministic no-op / tools/list).",
"configuration": "Server launched with the documented args per workload; no unrelated environment variables set."
},
"statistical_rules": {
"warmup": "Every scenario performs warm-up iterations that are discarded before measurement.",
"min_repetitions": 10,
"percentiles": ["p50", "p95", "p99"],
"reported_metrics": ["p50", "p95", "p99", "throughput", "cpu", "memory"],
"comparison": "Compare current vs approved baseline as ratios. Changes below 5% are ignored, changes above 5% warn, and budget breaches block. Prefer median/percentiles over the mean for latency.",
"notes": "Micro-benchmarks additionally report BenchmarkDotNet StdDev / confidence intervals; the host environment (OS, CPU, runtime) is captured in the BenchmarkDotNet report header."
},
"baseline_qualification": {
"min_successful_runs": 10,
"min_span_days": 14,
"controlled_runner_required": true,
"auto_update_after_regression": false,
"replacement_requires": ["linked issue", "measured impact", "owner approval"]
},
"workloads": [
{
"id": "startup-cli-cold",
"issue": 3118,
"harness": "eng/scripts/Test-StartupPerformance.ps1",
"transport": "cli",
"server_mode": null,
"description": "CLI cold start: 'azmcp tools list' (process spawn to exit).",
"warmup": "First run reported as cold; the remainder are warm.",
"repetitions": 10,
"metrics": ["p50", "p95", "p99", "cold_ms", "warm_median_ms"]
},
{
"id": "startup-stdio-default",
"issue": 3118,
"harness": "eng/scripts/Test-StartupPerformance.ps1",
"transport": "stdio",
"server_mode": "default",
"description": "MCP stdio startup to a usable tool list: 'server start' then initialize + tools/list (~71 tools).",
"warmup": "First run reported as cold; the remainder are warm.",
"repetitions": 10,
"metrics": ["p50", "p95", "p99", "full_schema_tokens_exact", "full_schema_serialize_ms"]
},
{
"id": "startup-stdio-namespace",
"issue": 3118,
"harness": "eng/scripts/Test-StartupPerformance.ps1",
"transport": "stdio",
"server_mode": "namespace",
"description": "MCP stdio startup with 'server start --mode namespace'.",
"warmup": "First run reported as cold; the remainder are warm.",
"repetitions": 10,
"metrics": ["p50", "p95", "p99"]
},
{
"id": "startup-stdio-all",
"issue": 3118,
"harness": "eng/scripts/Test-StartupPerformance.ps1",
"transport": "stdio",
"server_mode": "all",
"description": "MCP stdio startup with 'server start --mode all' (full tool surface, ~500+ tools).",
"warmup": "First run reported as cold; the remainder are warm.",
"repetitions": 10,
"metrics": ["p50", "p95", "p99", "full_schema_tokens_exact", "full_schema_serialize_ms"]
},
{
"id": "startup-http-default",
"issue": 3118,
"harness": "eng/scripts/Test-StartupPerformance.ps1",
"transport": "http",
"server_mode": "default",
"description": "MCP remote HTTP startup: initialize + tools/list over the HTTP transport, plus server readiness time.",
"warmup": "First run reported as cold; the remainder are warm.",
"repetitions": 10,
"metrics": ["p50", "p95", "p99", "readiness_ms"]
},
{
"id": "discovery-scaling",
"issue": 3118,
"harness": "ToolSurfaceScalingBenchmarks (BenchmarkDotNet)",
"transport": "in-process",
"server_mode": null,
"description": "tools/list serialization cost at current and projected tool counts.",
"tool_counts": [71, 250, 510, 1000],
"warmup": "BenchmarkDotNet warmup iterations.",
"repetitions": "BenchmarkDotNet default job (>=15 iterations).",
"metrics": ["mean", "allocated"]
},
{
"id": "dispatch-layers",
"issue": 3119,
"harness": "CommandDispatchBenchmarks (BenchmarkDotNet)",
"transport": "in-process",
"server_mode": null,
"description": "Per-layer command dispatch overhead (routing, parse, bind, validate, serialize, execute frame, full dispatch) on a deterministic no-op command; excludes Azure.",
"warmup": "BenchmarkDotNet warmup iterations.",
"repetitions": "BenchmarkDotNet default job (>=15 iterations).",
"metrics": ["mean", "allocated"]
},
{
"id": "dispatch-transport-stdio",
"issue": 3119,
"harness": "eng/scripts/Measure-DispatchOverhead.ps1",
"transport": "stdio",
"server_mode": "default",
"description": "tools/list request overhead over stdio.",
"warmup": "PERF_DISPATCH_WARMUP calls (default 20), not counted.",
"repetitions": 200,
"metrics": ["p50", "p95", "p99"]
},
{
"id": "dispatch-transport-http",
"issue": 3119,
"harness": "eng/scripts/Measure-DispatchOverhead.ps1",
"transport": "http",
"server_mode": "default",
"description": "tools/list request overhead over the HTTP transport; the http-minus-stdio p50 delta isolates transport cost.",
"warmup": "PERF_DISPATCH_WARMUP calls (default 20), not counted.",
"repetitions": 200,
"metrics": ["p50", "p95", "p99", "transport_overhead_tools_list_p50"]
},
{
"id": "resource-default",
"issue": 3121,
"harness": "eng/scripts/Measure-ResourceUsage.ps1",
"transport": "http",
"server_mode": "default",
"description": "CPU/memory/handle sampling across idle, startup, discovery, steady-state, and soak phases for the default tool surface.",
"phases": ["startup", "idle", "discovery", "steady_state", "soak"],
"concurrency": 4,
"warmup": "Soak analysis discards the first 25% of samples.",
"repetitions": "Continuous 100ms sampling per phase.",
"metrics": ["working_set_mb", "private_mb", "handles", "cpu_percent", "soak_slope"]
},
{
"id": "resource-all",
"issue": 3121,
"harness": "eng/scripts/Measure-ResourceUsage.ps1",
"transport": "http",
"server_mode": "all",
"description": "CPU/memory/handle sampling for the full tool surface.",
"phases": ["startup", "idle", "discovery", "steady_state", "soak"],
"concurrency": 4,
"warmup": "Soak analysis discards the first 25% of samples.",
"repetitions": "Continuous 100ms sampling per phase.",
"metrics": ["working_set_mb", "private_mb", "handles", "cpu_percent", "soak_slope"]
},
{
"id": "concurrency-sweep",
"issue": 3122,
"harness": "eng/scripts/Measure-ConcurrencyScaling.ps1",
"transport": "http",
"server_mode": "default",
"description": "Concurrency sweep over parallel MCP clients issuing tools/list; produces a saturation curve.",
"concurrency_levels": [1, 2, 4, 8, 16],
"warmup": "PERF_CONC_WARMUP_SECONDS per level (default 1s), not counted.",
"repetitions": "PERF_CONC_DURATION_SECONDS timed window per level (default 5s).",
"metrics": ["throughput_rps", "p50", "p95", "p99", "error_rate_pct", "scaling_efficiency", "tool_count_mismatches"]
}
]
}