diff --git a/scripts/startup/performance.py b/scripts/startup/performance.py index c6fe58170..6d8f47b92 100644 --- a/scripts/startup/performance.py +++ b/scripts/startup/performance.py @@ -30,6 +30,8 @@ RESULT_PREFIX = "MOVIEPILOT_IMPORT_BASELINE=" LIFECYCLE_RESULT_PREFIX = "MOVIEPILOT_LIFECYCLE_BASELINE=" PERFORMANCE_FACTOR = 2.0 PERFORMANCE_SLACK_MS = 500.0 +# 基线由维护者平台生成、CI 在 Linux runner 检查;给跨平台宽松预算保留小幅调度抖动带。 +PERFORMANCE_JITTER_FACTOR = 1.05 def measure_import(target: str) -> dict[str, Any]: @@ -311,7 +313,7 @@ def check_baseline( budget_ms = max( expected_target["max_ms"] * PERFORMANCE_FACTOR, expected_target["max_ms"] + PERFORMANCE_SLACK_MS, - ) + ) * PERFORMANCE_JITTER_FACTOR if actual_target["median_ms"] > budget_ms: errors.append( f"{target} 冷导入中位数 {actual_target['median_ms']}ms " diff --git a/tests/test_architecture_baseline_cli.py b/tests/test_architecture_baseline_cli.py index 098e6cf7d..395f16fea 100644 --- a/tests/test_architecture_baseline_cli.py +++ b/tests/test_architecture_baseline_cli.py @@ -636,6 +636,20 @@ def test_performance_check_ignores_environment_provenance_drift(): assert startup_performance.check_baseline(expected, actual) == [] +def test_performance_check_keeps_small_cross_platform_jitter_margin(): + """跨平台 runner 可使用 5% 抖动带,但超过最终预算仍必须失败。""" + expected = _performance_sample() + within_margin = _performance_sample() + within_margin["targets"]["app.factory"]["median_ms"] = 630.0 + above_margin = _performance_sample() + above_margin["targets"]["app.factory"]["median_ms"] = 630.001 + + assert startup_performance.check_baseline(expected, within_margin) == [] + assert startup_performance.check_baseline(expected, above_margin) == [ + "app.factory 冷导入中位数 630.001ms 超过预算 630.0ms" + ] + + def test_performance_check_reports_lifecycle_component_replacement(): """组件数量未变时,生命周期成员或顺序变化仍必须失败。""" expected = _performance_sample()