@@ -29,6 +29,9 @@ scene_size="$COMPARE_SCENE_SIZE"
2929warmup_seconds=" $COMPARE_WARMUP_SECONDS "
3030settle_seconds=" $COMPARE_SETTLE_SECONDS "
3131measure_seconds=" $COMPARE_MEASURE_SECONDS "
32+ # This only prevents the synthetic observer from being kicked while the
33+ # official upstream stalls; it does not alter the server's 20 TPS target.
34+ network_timeout_seconds=300
3235server_port=" ${COMPARE_SERVER_PORT:- 25565} "
3336protocol_trace_enabled=" ${COMPARE_PROTOCOL_TRACE_ENABLED:- 0} "
3437protocol_trace_max_events=" ${COMPARE_PROTOCOL_TRACE_MAX_EVENTS:- 500000} "
@@ -231,6 +234,11 @@ view-distance=4
231234white-list=false
232235EOF
233236
237+ cat > " $run_directory /spigot.yml" << EOF
238+ settings:
239+ timeout-time: $network_timeout_seconds
240+ EOF
241+
234242plugin_sha256=" $( sha256sum " $plugin_jar " | awk ' {print $1}' ) "
235243driver_sha256=" $( sha256sum " $driver_jar " | awk ' {print $1}' ) "
236244paper_sha256=" $( sha256sum " $paper_jar " | awk ' {print $1}' ) "
@@ -557,13 +565,16 @@ if data.get("effectiveFlags") != expected_effective_flags:
557565 f"comparison effective flags mismatch: "
558566 f"{data.get('effectiveFlags')!r} != {expected_effective_flags!r}"
559567 )
560- if data.get("seconds", 0) < measure - 2 or data.get("seconds", 0) > measure + 3:
561- raise SystemExit(f"comparison measurement duration is invalid: {data.get('seconds')}")
562- if data.get("tickSamples", 0) <= 0 or data.get("observedTps", 0) <= 0:
563- raise SystemExit("comparison produced no valid tick samples")
564568allows_upstream_saturation = (
565569 measure >= 60 and scenario == "block-active" and variant == "A"
566570)
571+ # The stop command is handled on the saturated main thread, so its wall-clock
572+ # acknowledgement can trail the requested window without invalidating it.
573+ maximum_seconds = measure + (30 if allows_upstream_saturation else 3)
574+ if data.get("seconds", 0) < measure - 2 or data.get("seconds", 0) > maximum_seconds:
575+ raise SystemExit(f"comparison measurement duration is invalid: {data.get('seconds')}")
576+ if data.get("tickSamples", 0) <= 0 or data.get("observedTps", 0) <= 0:
577+ raise SystemExit("comparison produced no valid tick samples")
567578if allows_upstream_saturation:
568579 # Sustained block load is allowed to expose the official upstream's
569580 # throughput ceiling. The rewritten candidate remains subject to the
@@ -636,7 +647,7 @@ python3 - "$run_directory/run-manifest.json" "$run_id" "$scenario" "$variant" \
636647 " $protocol_trace_aggregate_packet_allowlist " \
637648 " $trace_window_start_epoch_ms " " $trace_window_end_epoch_ms " \
638649 " $available_cpu_count " " $server_cpu_set " " $client_cpu_set " \
639- " $runtime_profile " " $metrics_path " << 'PY '
650+ " $runtime_profile " " $network_timeout_seconds " " $ metrics_path" << 'PY '
640651from pathlib import Path
641652import json
642653import sys
@@ -648,7 +659,7 @@ import sys
648659 trace_enabled, trace_packet_allowlist, trace_aggregate_packet_allowlist,
649660 trace_window_start_epoch_ms, trace_window_end_epoch_ms,
650661 available_cpu_count, server_cpu_set, client_cpu_set,
651- runtime_profile, metrics_path,
662+ runtime_profile, network_timeout_seconds, metrics_path,
652663) = sys.argv[1:]
653664metrics = json.load(open(metrics_path, encoding="utf-8"))
654665Path(output).write_text(json.dumps({
@@ -658,6 +669,7 @@ Path(output).write_text(json.dumps({
658669 "variant": variant,
659670 "variantMeaning": "official-upstream" if variant == "A" else "rewritten-candidate",
660671 "runtimeProfile": runtime_profile,
672+ "networkTimeoutSeconds": int(network_timeout_seconds),
661673 "requestedFlags": metrics["requestedFlags"],
662674 "effectiveFlags": metrics["effectiveFlags"],
663675 "sceneSize": int(scene_size),
0 commit comments