research: re-test L157/L160 on the incremental base (L167, none promoted)

7 runs each: L157 near 55.4% but a 16.7 ms worst tick (UpdateChunks/level sort/overlay); L160 tick-safe but lower
all-around near and later arrival; both: forward cone 25.2% and p99 <= 11 ms, but worst tick up and a 14.3 ms run.
Also found: voxel.StreamingIncrementalDesiredSet defaults to 0, so L165/L166 gains need it enabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016dhxM43dnWvUu2B5Ph1iG1
This commit is contained in:
Fr0zkaandClaude Opus 5.5 committed 2026-11-02 13:44:40 +01:00
1 parent c6357b573f
commit ec89b29853
3 files changed
+678

No files matched your search

@@ -0,0 +1,639 @@
#!/usr/bin/env python3
"""Interleaved L167 UE movement runs for the L157/L160 levers on the L165/L166 base."""
from __future__ import annotations
import argparse
import json
import math
import statistics
import subprocess
import time
from pathlib import Path
ROOT = Path(__file__).resolve().parents[4]
HOST = Path("/home/jahni/VFHost")
EDITOR = Path("/home/jahni/UnrealEngine/Engine/Binaries/Linux/UnrealEditor-Cmd")
OUT = ROOT / "Saved/Linux/l167/ue/movement"
HOST_SAVED = HOST / "Saved/Linux/l167"
HOST_PLUGIN_SAVED = HOST / "Plugins/VoxelForge/Saved/Linux/l167"
SPAWN_M = (19.166015625, -14.2001953125, -753.3740234375)
MOVE_START_S = 6.0
_COMMON = {
# Keep the faster L165/L166 path active for every condition; omit its audit
# during timing so the audit itself cannot create a frame spike.
"incremental_desired": 1, "audit_every": 0,
"materialization_audit_every": 0, "inject_mismatch": 0,
}
CONDITIONS = {
"base": {
**_COMMON, "wait_for_critical": 1, "apply_budget_ms": 0.0,
"forward_first": 0, "rebuild_on_region_completion": 1,
"core_desired_cache": 0,
},
"l157": {
**_COMMON, "wait_for_critical": 0, "apply_budget_ms": 1.0,
"forward_first": 0, "rebuild_on_region_completion": 1,
"core_desired_cache": 0,
},
"l160": {
**_COMMON, "wait_for_critical": 1, "apply_budget_ms": 0.0,
"forward_first": 1, "rebuild_on_region_completion": 0,
"core_desired_cache": 1,
},
"both": {
**_COMMON, "wait_for_critical": 0, "apply_budget_ms": 1.0,
"forward_first": 1, "rebuild_on_region_completion": 0,
"core_desired_cache": 1,
},
}
ORDER = {
1: ("base", "l157", "l160", "both"),
2: ("l157", "l160", "both", "base"),
3: ("l160", "both", "base", "l157"),
4: ("both", "base", "l157", "l160"),
5: ("l160", "l157", "base", "both"),
6: ("both", "l160", "l157", "base"),
7: ("base", "both", "l160", "l157"),
}
def percentile(values: list[float], fraction: float = 0.99) -> float | None:
if not values:
return None
ordered = sorted(values)
return ordered[max(0, min(len(ordered) - 1, math.ceil(len(ordered) * fraction) - 1))]
def read_events(path: Path) -> list[dict]:
rows = []
if path.is_file():
for line in path.read_text(encoding="utf-8", errors="replace").splitlines():
if not line.startswith("{"):
continue
try:
rows.append(json.loads(line))
except json.JSONDecodeError:
continue
return rows
def mean(values: list[float]) -> float | None:
return statistics.mean(values) if values else None
def desired_breakdown(events: list[dict], move_start_s: float, stop_s: float) -> dict:
rows = [event for event in events
if event.get("type") == "desired_rebuild_breakdown"
and move_start_s <= float(event.get("t_s", 0.0)) < stop_s]
keys = ("total_ms", "core_prepare_ms", "core_delta_ms", "fallback_ms",
"overlay_materialize_ms", "priority_sort_ms", "critical_order_ms")
result = {"rebuild_count": len(rows)}
result["incremental_materialization_update_count"] = sum(
int(event.get("materialization_update", 0)) != 0 for event in rows)
result["priority_order_reuse_count"] = sum(
int(event.get("priority_order_reused", 0)) != 0 for event in rows)
result["priority_order_update_count"] = sum(
int(event.get("priority_order_updated", 0)) != 0 for event in rows)
result["incremental_materialization_update_share_pct"] = percent(
result["incremental_materialization_update_count"], len(rows))
result["priority_order_reuse_share_pct"] = percent(
result["priority_order_reuse_count"], len(rows))
result["priority_order_update_share_pct"] = percent(
result["priority_order_update_count"], len(rows))
for key in keys:
values = [float(event.get(key, 0.0)) for event in rows]
result[f"{key}_p50"] = statistics.median(values) if values else None
result[f"{key}_p95"] = percentile(values, 0.95)
result[f"{key}_max"] = max(values) if values else None
fallback_rows = [event for event in events
if event.get("type") == "core_desired_cache"
and move_start_s <= float(event.get("t_s", 0.0)) < stop_s
and int(event.get("full_fallback", 0)) != 0]
result["fallback_count"] = len(fallback_rows)
result["lod4plus_fallback_count"] = sum(
int(event.get("fallback_reason", 0)) == 1 for event in fallback_rows)
result["other_fallback_count"] = sum(
int(event.get("fallback_reason", 0)) == 2 for event in fallback_rows)
result["fallback_cost_sum_ms"] = sum(
float(event.get("fallback_ms", 0.0)) for event in fallback_rows)
result["fallback_cost_max_ms"] = max(
(float(event.get("fallback_ms", 0.0)) for event in fallback_rows), default=None)
return result
def percent(numerator: int | float, denominator: int | float) -> float | None:
return 100.0 * numerator / denominator if denominator > 0 else None
def run(condition: str, repetition: int, tile_hash_dump: Path | None = None,
expected_mismatch: bool = False) -> dict:
config = CONDITIONS[condition]
run_name = f"fast-r{repetition}"
out = OUT / condition
host_out = HOST_PLUGIN_SAVED / condition / "output"
userdir = HOST_SAVED / "user" / condition / run_name
zendata = HOST_SAVED / "zen" / condition / run_name
ddc = HOST_SAVED / "DDC"
trace = out / f"{run_name}.trace.jsonl"
abslog = out / f"{run_name}.log"
stdout = out / f"{run_name}.stdout.log"
export = host_out / run_name
for directory in (out, export, userdir, zendata, ddc):
directory.mkdir(parents=True, exist_ok=True)
trace.unlink(missing_ok=True)
spawn_cm = ",".join(f"{value * 100.0:.3f}" for value in SPAWN_M)
command = [
str(EDITOR), str(HOST / "VFHost.uproject"), "-nullrhi", "-unattended",
"-nop4", "-nosplash", "-NoSound", "-corelimit=12", "-NoZenAutoLaunch",
"-notraceserver", "-nocrashreports", "-DisablePlugins=AndroidFileServer",
"-ddc=NoZenLocalFallback", f"-userdir={userdir}", f"-ZenDataPath={zendata}",
f"-LocalDataCachePath={ddc}", "-run=VoxelForgeExplore", "-seed=0",
"-archetype=TunnelNetwork", "-slot=0", "-modes=export", "-gameconfig=1",
"-coreworldtest=1", "-ownerfourstrateplan=1", "-corevoxelsizecm=25",
"-coreislandtest=0", "-corefallbacktest=0", "-coreofftest=0",
"-coreplantest=0", "-settingsref=/Game/VoxelForge/DA_Settings.DA_Settings",
"-corehybridmesher=0", f"-out={export}", "-voxel.StreamingCoarseFirst=1",
"-voxel.StreamingDynamicNearReserve=1",
"-voxel.StreamingLegacyPendingResultCap=0",
"-voxel.CoreRegionConcurrentAdmission=1",
"-voxel.StreamingResultBacklogCap=256", "-voxel.StreamingReadyQueueDepth=8",
"-voxel.StreamingBackgroundWorkerCap=1", "-voxel.CoreColumnCacheDirectMapped=0",
"-voxel.StreamingFarApplySupplement=1",
f"-voxel.StreamingFastTravelWaitForAllCriticalTiles={config['wait_for_critical']}",
f"-voxel.StreamingFastTravelApplyBudgetMilliseconds={config['apply_budget_ms']:.1f}",
f"-voxel.StreamingFastTravelForwardFirst={config['forward_first']}",
f"-voxel.StreamingRebuildOnCoreRegionCompletion={config['rebuild_on_region_completion']}",
f"-voxel.StreamingCoreDesiredCacheByCenter={config['core_desired_cache']}",
f"-voxel.StreamingIncrementalDesiredSet={config['incremental_desired']}",
f"-voxel.StreamingIncrementalDesiredAuditEvery={config['audit_every']}",
f"-voxel.StreamingIncrementalDesiredMaterializationAuditEvery={config['materialization_audit_every']}",
f"-voxel.StreamingIncrementalDesiredAuditInjectMismatch={config['inject_mismatch']}",
"-voxel.CoreMCGradientMemoization=1", "-voxel.StreamingCollisionLookahead=1",
"-voxel.TestMove=1", "-voxel.TestMoveSpeedCmPerSecond=3000.0",
f"-voxel.TestMoveStartSeconds={MOVE_START_S:.1f}",
"-voxel.TestMoveDurationSeconds=12.0", "-voxel.TestExitSeconds=0.0",
"-voxel.TestMoveDirection=1,0,0", "-voxel.StreamingSchedulerPolicy=3",
"-voxel.TestExitOnSteady=0", "-coreworldstreamtrace=1",
f"-voxel.StartupTraceSpawnCm={spawn_cm}",
"-voxel.StartupTraceUntilEndPlay=1", "-voxel.StartupTraceThroughCrossing=1",
"-voxel.StartupTraceMaxTiles=16384", f"-voxel.StartupTraceFile={trace}",
f"-abslog={abslog}",
]
if tile_hash_dump is not None:
tile_hash_dump.parent.mkdir(parents=True, exist_ok=True)
tile_hash_dump.unlink(missing_ok=True)
command.append(f"-voxel.TileHashDump={tile_hash_dump.resolve()}")
wrapped = ["taskset", "-c", "0-11", "timeout", "1740s", *command]
started = time.monotonic()
with stdout.open("w", encoding="utf-8") as stream:
process = subprocess.run(
wrapped, cwd=ROOT, stdout=stream, stderr=subprocess.STDOUT,
check=False, timeout=1740)
events = read_events(trace)
if expected_mismatch:
diagnostic = "VoxelForgeIncrementalDesiredAudit"
logs = "\n".join(path.read_text(encoding="utf-8", errors="replace")
for path in (abslog, stdout) if path.is_file())
audit_events = [event for event in events
if event.get("type") in {"incremental_desired_audit",
"incremental_desired_order_audit"}]
failed_audit = any(int(event.get("pass", 1)) == 0 for event in audit_events)
failed_audit = failed_audit or (
diagnostic in logs and "mismatch" in logs.lower())
if process.returncode == 0 or diagnostic not in logs or "mismatch" not in logs.lower():
raise RuntimeError(
f"injected mismatch did not fail as expected: exit={process.returncode}; "
f"audit_events={len(audit_events)}; log={abslog}")
print("[L166MismatchControl] " + json.dumps({
"exit_code": process.returncode,
"diagnostic_seen": True,
"failed_audit_event_seen": failed_audit,
"trace": str(trace.relative_to(ROOT)),
"log": str(abslog.relative_to(ROOT)),
}, sort_keys=True), flush=True)
return {"condition": condition, "exit_code": process.returncode,
"failed_audit_event_seen": failed_audit}
samples = [event for event in events if event.get("type") == "streaming_sample"]
moving = [event for event in samples if float(event.get("speed_cm_s", 0.0)) >= 50.0]
stop_event = next((event for event in events
if event.get("type") == "streaming_test_move_stopped"), None)
backend = next((event for event in events if event.get("type") == "worker_backend_config"), {})
scheduler_config = next((event for event in events
if event.get("type") == "scheduler_admission"), {})
worker_cap = next((event for event in events
if event.get("type") == "streaming_worker_cap_readback"), {})
if stop_event is None:
raise RuntimeError(f"missing move-stop event: {trace}")
stop_s = float(stop_event.get("t_s", 0.0))
move_start_s = min((float(event.get("t_s", 0.0)) for event in moving), default=float("inf"))
dwell = [event for event in samples if float(event.get("t_s", 0.0)) >= stop_s
and float(event.get("speed_cm_s", 0.0)) < 50.0]
arrival = [event for event in samples if float(event.get("t_s", 0.0)) < move_start_s
and float(event.get("speed_cm_s", 0.0)) < 50.0]
desired_stage_breakdown = desired_breakdown(events, move_start_s, stop_s)
if process.returncode or len(moving) < 40 or len(dwell) < 16:
raise RuntimeError(f"incomplete {condition} run: {trace}; exit={process.returncode}; "
f"move={len(moving)} dwell={len(dwell)}")
if (int(backend.get("streaming_fast_travel_wait_for_all_critical_tiles", -1))
!= config["wait_for_critical"]
or abs(float(backend.get("streaming_fast_travel_apply_budget_ms", -1.0))
- config["apply_budget_ms"]) > 0.01
or int(worker_cap.get("streaming_background_worker_cap", -1)) != 1
or int(backend.get("effective_tile_slots", -1)) != 8
or int(backend.get("streaming_far_apply_supplement", -1)) != 1
or int(scheduler_config.get("forward_first", -1)) != config["forward_first"]
or int(scheduler_config.get("rebuild_on_core_region_completion", -1))
!= config["rebuild_on_region_completion"]
or int(scheduler_config.get("core_desired_cache_by_center", -1))
!= config["core_desired_cache"]
or int(scheduler_config.get("incremental_desired_set", -1))
!= config["incremental_desired"]
or int(scheduler_config.get("incremental_desired_audit_every", -1))
!= config["audit_every"]
or int(scheduler_config.get("incremental_desired_materialization_audit_every", -1))
!= config["materialization_audit_every"]
or int(scheduler_config.get("incremental_desired_audit_inject_mismatch", -1))
!= config["inject_mismatch"]):
raise RuntimeError(f"CVar/worker readback mismatch: {backend}; {worker_cap}; {scheduler_config}")
moving_metrics = []
for event in moving:
desired = event.get("desired_by_lod", [0] * 9)
resident = event.get("resident_by_lod", [0] * 9)
near_desired = sum(desired[:3])
cone_desired = int(event.get("near_forward_cone_desired", 0))
view_cone_desired = int(event.get("near_view_forward_cone_desired", 0))
view_valid = bool(event.get("near_view_forward_cone_valid", 0))
weighted_desired = float(event.get("near_forward_weighted_desired", 0.0))
travel_cone_ready = percent(
int(event.get("near_forward_cone_resident", 0)), cone_desired)
view_cone_ready = percent(
int(event.get("near_view_forward_cone_resident", 0)), view_cone_desired)
moving_metrics.append({
"near_ready_pct": percent(sum(resident[:3]), near_desired) or 0.0,
"lod0_ready_pct": percent(resident[0], desired[0]) or 0.0,
"lod1_ready_pct": percent(resident[1], desired[1]) or 0.0,
"lod2_ready_pct": percent(resident[2], desired[2]) or 0.0,
"far_hole_pct": percent(
sum(desired[3:]) - sum(event.get("covered_by_lod", resident)[3:]),
sum(desired[3:])) or 0.0,
"ahead_share_pct": percent(int(event.get("near_ahead_desired", 0)), near_desired),
"behind_share_pct": percent(int(event.get("near_behind_desired", 0)), near_desired),
"side_share_pct": 100.0 - (
percent(int(event.get("near_ahead_desired", 0)), near_desired) or 0.0
) - (
percent(int(event.get("near_behind_desired", 0)), near_desired) or 0.0
),
"ahead_ready_pct": percent(
int(event.get("near_ahead_resident", 0)),
int(event.get("near_ahead_desired", 0))),
"behind_ready_pct": percent(
int(event.get("near_behind_resident", 0)),
int(event.get("near_behind_desired", 0))),
"travel_forward_cone_ready_pct": travel_cone_ready,
"view_forward_cone_ready_pct": view_cone_ready,
"forward_cone_ready_pct": view_cone_ready if view_valid else travel_cone_ready,
"forward_cone_source": "camera" if view_valid else "travel_fallback",
"forward_cone_share_pct": percent(cone_desired, near_desired),
"forward_weighted_ready_pct": percent(
float(event.get("near_forward_weighted_resident", 0.0)), weighted_desired),
})
arrival_near_settled = next((event for event in arrival
if sum(event.get("desired_by_lod", [0] * 9)[:3]) > 0
and sum(event.get("settled_by_lod", [0] * 9)[:3])
>= sum(event.get("desired_by_lod", [0] * 9)[:3])), None)
dwell_complete = next((event for event in dwell
if sum(event.get("resident_by_lod", [0] * 9)[:3])
>= sum(event.get("desired_by_lod", [0] * 9)[:3])
and sum(event.get("desired_by_lod", [0] * 9)[3:])
<= sum(event.get("covered_by_lod", [0] * 9)[3:])), None)
work = [event for event in events if event.get("type") == "game_thread_work_frame"
and move_start_s <= float(event.get("t_s", 0.0)) < stop_s]
applies = {event.get("frame"): event for event in events
if event.get("type") == "apply_frame"
and move_start_s <= float(event.get("t_s", 0.0)) < stop_s}
scheduler = {event.get("frame"): event for event in events
if event.get("type") == "scheduler_admission"
and move_start_s <= float(event.get("t_s", 0.0)) < stop_s}
frames = []
for event in work:
apply = applies.get(event.get("frame"), {})
admit = scheduler.get(event.get("frame"), {})
frames.append({
"frame": event.get("frame"),
"tick_ms": float(event.get("tick_ms", 0.0)),
"update_chunks_ms": float(event.get("update_chunks_ms", 0.0)),
"pending_drain_ms": float(event.get("pending_drain_ms", 0.0)),
"apply_ms": float(apply.get("apply_ms", 0.0)),
"apply_budget_ms": float(apply.get("apply_budget_ms", 0.0)),
"meshes_applied": int(apply.get("meshes_applied", 0)),
"time_budget_hit": int(apply.get("time_limit_reached", 0)),
"desired_rebuild_ms": float(admit.get("desired_rebuild_ms", 0.0)),
"desired_rebuilt": int(admit.get("desired_rebuilt", 0)),
"submit_tiles_ms": float(admit.get("submit_tiles_ms", 0.0)),
"level_admit_ms": float(admit.get("level_admit_ms", 0.0)),
})
p99_field = lambda key: percentile([float(row[key]) for row in frames])
max_field = lambda key: max((float(row[key]) for row in frames), default=None)
rebuild_frames = [row for row in frames if row["desired_rebuilt"]]
rebuild_costs = [float(row["desired_rebuild_ms"]) for row in rebuild_frames]
moving_scheduler = [event for event in scheduler.values()]
center_crossings = 0
previous_center = None
for event in sorted(moving_scheduler, key=lambda item: int(item.get("frame", 0))):
center = tuple(event.get("center", ()))
if previous_center is not None and center != previous_center:
center_crossings += 1
previous_center = center
core_requests = [event for event in events
if event.get("type") == "core_region_compile_request"
and move_start_s <= float(event.get("t_s", 0.0)) < stop_s]
same_center_core_requests = sum(
event.get("reason") == "desired_set_changed_same_center" for event in core_requests)
core_desired_queries = [event for event in events
if event.get("type") == "core_desired_cache"
and move_start_s <= float(event.get("t_s", 0.0)) < stop_s]
core_desired_query_ms = [float(event.get("query_ms", 0.0))
for event in core_desired_queries if float(event.get("query_ms", 0.0)) > 0.0]
core_desired_cache_hits = sum(int(event.get("hit", 0)) for event in core_desired_queries)
incremental_audits = [event for event in events
if event.get("type") == "incremental_desired_audit"
and move_start_s <= float(event.get("t_s", 0.0)) < stop_s]
incremental_audit_failures = sum(int(event.get("pass", 1)) == 0
for event in incremental_audits)
order_audits = [event for event in events
if event.get("type") == "incremental_desired_order_audit"
and move_start_s <= float(event.get("t_s", 0.0)) < stop_s]
order_audit_failures = sum(int(event.get("pass", 1)) == 0 for event in order_audits)
materialization_audits = [event for event in incremental_audits
if int(event.get("materialization_audit", 0)) != 0]
if config["audit_every"] > 0 and (
not incremental_audits or incremental_audit_failures
or not order_audits or order_audit_failures
or (config["materialization_audit_every"] > 0
and not materialization_audits)):
raise RuntimeError(
f"incremental desired equality audit missing/failed: {trace}; "
f"set={len(incremental_audits)}/{incremental_audit_failures} "
f"order={len(order_audits)}/{order_audit_failures} "
f"materialization={len(materialization_audits)}")
direction_submissions = [event.get("near_submitted_by_direction", [0, 0, 0, 0])
for event in moving_scheduler]
direction_submissions = [counts for counts in direction_submissions
if isinstance(counts, list) and len(counts) == 4]
direction_submission_totals = [
sum(int(counts[index]) for counts in direction_submissions) for index in range(4)
]
first_admission_order = next((event.get("near_admission_order_first", [])
for event in moving_scheduler
if event.get("near_admission_order_first")), [])
camera_samples = sum(bool(event.get("near_view_forward_cone_valid", 0)) for event in moving)
dwell_complete_s = (float(dwell_complete.get("t_s", 0.0)) - stop_s
if dwell_complete else None)
row = {
"condition": condition,
"repetition": repetition,
"speed_mps": 30.0,
"wait_for_all_critical_tiles": config["wait_for_critical"],
"fast_travel_apply_budget_ms": config["apply_budget_ms"],
"forward_first": config["forward_first"],
"rebuild_on_core_region_completion": config["rebuild_on_region_completion"],
"core_desired_cache_by_center": config["core_desired_cache"],
"incremental_desired_set": config["incremental_desired"],
"incremental_desired_audit_every": config["audit_every"],
"incremental_desired_materialization_audit_every": config["materialization_audit_every"],
"incremental_desired_audit_count": len(incremental_audits),
"incremental_desired_audit_failures": incremental_audit_failures,
"incremental_desired_order_audit_count": len(order_audits),
"incremental_desired_order_audit_failures": order_audit_failures,
"incremental_desired_materialization_audit_count": len(materialization_audits),
"effective_tile_slots": backend.get("effective_tile_slots"),
"exit_code": process.returncode,
"wall_s": round(time.monotonic() - started, 3),
"moving_samples": len(moving),
"dwell_samples": len(dwell),
"arrival_samples": len(arrival),
"near_ready_moving_mean_pct": mean([m["near_ready_pct"] for m in moving_metrics]),
"lod0_ready_moving_mean_pct": mean([m["lod0_ready_pct"] for m in moving_metrics]),
"lod1_ready_moving_mean_pct": mean([m["lod1_ready_pct"] for m in moving_metrics]),
"lod2_ready_moving_mean_pct": mean([m["lod2_ready_pct"] for m in moving_metrics]),
"far_holes_moving_mean_pct": mean([m["far_hole_pct"] for m in moving_metrics]),
"near_ahead_desired_share_pct": mean([m["ahead_share_pct"] for m in moving_metrics
if m["ahead_share_pct"] is not None]),
"near_behind_desired_share_pct": mean([m["behind_share_pct"] for m in moving_metrics
if m["behind_share_pct"] is not None]),
"near_side_desired_share_pct": mean([m["side_share_pct"] for m in moving_metrics]),
"near_ahead_ready_pct": mean([m["ahead_ready_pct"] for m in moving_metrics
if m["ahead_ready_pct"] is not None]),
"near_behind_ready_pct": mean([m["behind_ready_pct"] for m in moving_metrics
if m["behind_ready_pct"] is not None]),
"near_forward_cone_half_angle_deg": 55,
"near_forward_cone_desired_share_pct": mean([m["forward_cone_share_pct"]
for m in moving_metrics
if m["forward_cone_share_pct"] is not None]),
"near_forward_cone_ready_pct": mean([m["forward_cone_ready_pct"]
for m in moving_metrics
if m["forward_cone_ready_pct"] is not None]),
"near_travel_forward_cone_ready_pct": mean(
[m["travel_forward_cone_ready_pct"] for m in moving_metrics
if m["travel_forward_cone_ready_pct"] is not None]),
"near_view_forward_cone_ready_pct": mean(
[m["view_forward_cone_ready_pct"] for m in moving_metrics
if m["view_forward_cone_ready_pct"] is not None]),
"camera_forward_samples": camera_samples,
"camera_forward_sample_share_pct": percent(camera_samples, len(moving)),
"near_forward_cosine_weighted_ready_pct": mean(
[m["forward_weighted_ready_pct"] for m in moving_metrics
if m["forward_weighted_ready_pct"] is not None]),
"arrival_lod02_settled_t_s": (
float(arrival_near_settled.get("t_s", 0.0)) if arrival_near_settled else None),
"near_ready_dwell_end_pct": (100.0 * sum(dwell[-1].get("resident_by_lod", [0] * 9)[:3])
/ max(1, sum(dwell[-1].get("desired_by_lod", [0] * 9)[:3]))),
"far_holes_dwell_end_pct": (100.0 * (
sum(dwell[-1].get("desired_by_lod", [0] * 9)[3:])
- sum(dwell[-1].get("covered_by_lod", [0] * 9)[3:]))
/ max(1, sum(dwell[-1].get("desired_by_lod", [0] * 9)[3:]))),
"dwell_complete_after_stop_s": dwell_complete_s,
"game_thread_tick_p99_ms": p99_field("tick_ms"),
"game_thread_tick_max_ms": max_field("tick_ms"),
"stream_update_p99_ms": p99_field("update_chunks_ms"),
"pending_drain_p99_ms": p99_field("pending_drain_ms"),
"apply_p99_ms": p99_field("apply_ms"),
"apply_max_ms": max_field("apply_ms"),
"apply_budget_min_ms": min((f["apply_budget_ms"] for f in frames), default=None),
"apply_budget_max_ms": max((f["apply_budget_ms"] for f in frames), default=None),
"apply_time_budget_hit_frames": sum(f["time_budget_hit"] for f in frames),
"apply_frames": sum(f["meshes_applied"] > 0 for f in frames),
"apply_meshes_total": sum(f["meshes_applied"] for f in frames),
"desired_rebuild_p99_ms": p99_field("desired_rebuild_ms"),
"desired_rebuild_count": len(rebuild_frames),
"desired_rebuilds_per_second": len(rebuild_frames) / 12.0,
"center_crossings": center_crossings,
"same_center_core_region_requests": same_center_core_requests,
"core_desired_cache_hit_count": core_desired_cache_hits,
"core_desired_cache_hit_share_pct": percent(
core_desired_cache_hits, len(core_desired_queries)),
"core_desired_query_nonzero_p50_ms": statistics.median(core_desired_query_ms)
if core_desired_query_ms else None,
"core_desired_query_nonzero_p95_ms": percentile(core_desired_query_ms, 0.95),
"core_desired_query_nonzero_max_ms": max(core_desired_query_ms)
if core_desired_query_ms else None,
"desired_rebuild_nonzero_p50_ms": statistics.median(rebuild_costs)
if rebuild_costs else None,
"desired_rebuild_nonzero_p95_ms": percentile(rebuild_costs, 0.95),
"desired_rebuild_nonzero_max_ms": max(rebuild_costs) if rebuild_costs else None,
"desired_breakdown": desired_stage_breakdown,
"near_submitted_by_direction": direction_submission_totals,
"near_admission_first12": first_admission_order,
"submit_tiles_p99_ms": p99_field("submit_tiles_ms"),
"level_admit_p99_ms": p99_field("level_admit_ms"),
"top_tick_frames": sorted(frames, key=lambda f: f["tick_ms"], reverse=True)[:5],
"trace": str(trace.relative_to(ROOT)),
"log": str(abslog.relative_to(ROOT)),
}
print("[L167Movement] " + json.dumps(row, sort_keys=True), flush=True)
return row
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--smoke", action="store_true",
help="run one unmeasured base warm-up and validate CVar readback")
parser.add_argument("--resume", action="store_true",
help="resume an incomplete matrix from runs-partial.json")
parser.add_argument("--summarize-existing", action="store_true",
help="summarize 28 completed matrix rows without rerunning UE")
args = parser.parse_args()
missing = [path for path in (EDITOR, HOST / "VFHost.uproject") if not path.exists()]
if missing:
raise SystemExit(f"missing UE runner input: {missing}")
OUT.mkdir(parents=True, exist_ok=True)
partial = OUT / "runs-partial.json"
if args.smoke:
run("base", 0)
return 0
if args.summarize_existing:
if not partial.is_file():
raise RuntimeError(f"no saved movement rows: {partial}")
rows = json.loads(partial.read_text(encoding="utf-8"))
else:
if partial.is_file() and not args.resume:
raise RuntimeError(f"partial matrix exists; use --resume or move it first: {partial}")
rows = json.loads(partial.read_text(encoding="utf-8")) if partial.is_file() else []
if not rows:
# One editor binary is used by every condition, so one warm-up is enough.
run("base", 0)
completed = {(row["repetition"], row["condition"]) for row in rows}
for repetition in range(1, 8):
for condition in ORDER[repetition]:
if (repetition, condition) in completed:
continue
row = run(condition, repetition)
rows.append(row)
partial.write_text(json.dumps(rows, indent=2, sort_keys=True) + "\n",
encoding="utf-8")
metrics = (
"near_ready_moving_mean_pct", "far_holes_moving_mean_pct",
"game_thread_tick_p99_ms", "game_thread_tick_max_ms",
"arrival_lod02_settled_t_s", "dwell_complete_after_stop_s",
"near_ahead_ready_pct", "near_behind_ready_pct",
"near_forward_cone_ready_pct", "near_forward_cosine_weighted_ready_pct",
"apply_p99_ms", "apply_max_ms", "desired_rebuild_nonzero_p95_ms",
"stream_update_p99_ms", "pending_drain_p99_ms", "submit_tiles_p99_ms",
"level_admit_p99_ms", "desired_rebuild_count", "center_crossings",
)
def median_for(condition: str, metric: str) -> float | None:
values = [row[metric] for row in rows
if row["condition"] == condition and row.get(metric) is not None]
return statistics.median(values) if values else None
medians = {
condition: {metric: median_for(condition, metric) for metric in metrics}
for condition in CONDITIONS
}
gates = {}
paired_deltas = {}
for candidate in ("l157", "l160", "both"):
candidate_rows = [row for row in rows if row["condition"] == candidate]
candidate_median_worst = median_for(candidate, "game_thread_tick_max_ms")
base_median_worst = median_for("base", "game_thread_tick_max_ms")
candidate_near = median_for(candidate, "near_ready_moving_mean_pct")
base_near = median_for("base", "near_ready_moving_mean_pct")
candidate_cone = median_for(candidate, "near_forward_cone_ready_pct")
base_cone = median_for("base", "near_forward_cone_ready_pct")
candidate_far = median_for(candidate, "far_holes_moving_mean_pct")
base_far = median_for("base", "far_holes_moving_mean_pct")
candidate_arrival = median_for(candidate, "arrival_lod02_settled_t_s")
base_arrival = median_for("base", "arrival_lod02_settled_t_s")
candidate_gates = {
"seven_runs_complete": len(candidate_rows) == 7,
"every_run_p99_le_11_ms": len(candidate_rows) == 7 and all(
row["game_thread_tick_p99_ms"] <= 11.0 for row in candidate_rows),
"median_worst_tick_no_worse": (
candidate_median_worst is not None and base_median_worst is not None
and candidate_median_worst <= base_median_worst),
"no_run_worst_tick_above_14_ms": len(candidate_rows) == 7 and all(
row["game_thread_tick_max_ms"] <= 14.0 for row in candidate_rows),
"median_near_readiness_up": (
candidate_near is not None and base_near is not None
and candidate_near > base_near),
"median_forward_cone_readiness_up": (
candidate_cone is not None and base_cone is not None
and candidate_cone > base_cone),
"median_far_holes_no_worse": (
candidate_far is not None and base_far is not None
and candidate_far <= base_far),
"median_arrival_no_worse": (
candidate_arrival is not None and base_arrival is not None
and candidate_arrival <= base_arrival),
}
gates[candidate] = {
**candidate_gates,
"passes_default_bar": all(candidate_gates.values()),
}
paired_deltas[candidate] = []
for repetition in range(1, 8):
by_condition = {row["condition"]: row for row in rows
if row["repetition"] == repetition}
if candidate not in by_condition or "base" not in by_condition:
continue
paired_deltas[candidate].append({
"repetition": repetition,
**{f"{metric}_delta": by_condition[candidate][metric]
- by_condition["base"][metric]
for metric in metrics if by_condition[candidate].get(metric) is not None
and by_condition["base"].get(metric) is not None},
})
summary = {
"source_commit": subprocess.run(
["git", "-c", f"safe.directory={ROOT}", "rev-parse", "HEAD"],
cwd=ROOT, check=True, capture_output=True, text=True).stdout.strip(),
"protocol": "Seven interleaved 30 m/s W8 UE runs per condition; 12 s move plus 5 s dwell; 8 effective tile slots; one base warm-up.",
"conditions": CONDITIONS,
"movement_medians": medians,
"candidate_gates": gates,
"paired_deltas_vs_base": paired_deltas,
"runs": rows,
}
(OUT / "summary.json").write_text(
json.dumps(summary, indent=2, sort_keys=True) + "\n", encoding="utf-8")
print("[L167Summary] " + json.dumps({
"movement_medians": medians,
"candidate_gates": gates,
"runs": len(rows),
}, sort_keys=True), flush=True)
return 0
if __name__ == "__main__":
raise SystemExit(main())