优化原生结果编码传输与浏览器缓存,记录八路性能基线

原生结果series通过字节索引直传,C端使用Ryu精确回读编码和64 KiB批量写出;网页采用Float64缓存和CSV工作线程,减少结果处理与保存等待。

补充八路AME曲线核查、全流程分阶段计时、独立编码基准和复现工具,固定后续优化采用修正八路及rtol=1e-8。C写出1.1808→0.1638 s,点击到可查看8.0100→6.9756 s。

验证:最终10项编码专项、29项相关后端回归通过;8份原生结果逐位一致,16次网页结果/CSV/刷新恢复通过。前端构建及缓存/CSV专项在本轮结果处理工作中通过。环境、原始大结果与临时构建不纳入Git。
This commit is contained in:
lujingze committed 2026-09-11 15:09:15 +00:00
1 parent 808c484f5b
commit 3bc4be3c06
55 files changed
+20522 -141

No files matched your search

+22 -7
View File
@@ -23,6 +23,7 @@ from fastapi.responses import FileResponse, HTMLResponse, StreamingResponse
from pydantic import BaseModel, ConfigDict, Field, ValidationError
from app.simulation.performance import performance_span, profile_phase, profile_run
from app.simulation.native_codegen.transport import NativeSeriesJson, serialize_result_parts
from app.simulation.config import SolverActivityTracker
from app.system_xml import (
SystemXmlDocument,
@@ -652,7 +653,7 @@ async def simulate_system_xml_stream(request: Request) -> StreamingResponse:
simulation_id = request.headers.get("x-simulation-id") or uuid4().hex
task = _register_simulation_task(simulation_id)
return StreamingResponse(
simulation_event_stream(await request.body(), task=task),
simulation_event_stream(await request.body(), task=task, raw_series=True),
media_type="application/x-ndjson",
headers={
"Cache-Control": "no-cache, no-transform",
@@ -679,13 +680,17 @@ def cancel_system_xml_simulation(
}
@app.get("/api/system-xml/simulations/{simulation_id}")
def get_system_xml_simulation(simulation_id: str) -> dict[str, object]:
@app.get("/api/system-xml/simulations/{simulation_id}", response_model=None)
def get_system_xml_simulation(simulation_id: str) -> dict[str, object] | Response:
with SIMULATION_TASKS_LOCK:
task = SIMULATION_TASKS.get(simulation_id)
if task is None:
raise HTTPException(status_code=404, detail="Simulation task was not found.")
return _simulation_task_snapshot(task)
snapshot = _simulation_task_snapshot(task)
result = snapshot.get("result")
if isinstance(result, dict) and isinstance(result.get("series"), NativeSeriesJson):
return StreamingResponse(iter(serialize_result_parts(snapshot)), media_type="application/json")
return snapshot
def run_system_xml_simulation(
@@ -693,6 +698,7 @@ def run_system_xml_simulation(
progress_callback: SimulationProgressEmitter | None = None,
cancel_check: Callable[[], bool] | None = None,
activity_tracker: SolverActivityTracker | None = None,
*, raw_series: bool = False,
) -> dict[str, object]:
with profile_run() as trace:
result = _run_system_xml_simulation_profiled(
@@ -700,6 +706,7 @@ def run_system_xml_simulation(
progress_callback,
cancel_check,
activity_tracker,
raw_series=raw_series,
)
performance = trace.snapshot()
@@ -715,6 +722,7 @@ def _run_system_xml_simulation_profiled(
progress_callback: SimulationProgressEmitter | None = None,
cancel_check: Callable[[], bool] | None = None,
activity_tracker: SolverActivityTracker | None = None,
*, raw_series: bool = False,
) -> dict[str, object]:
from app.simulation.backends import simulate_network
from app.simulation.results import SimulationPreparationError
@@ -762,6 +770,7 @@ def _run_system_xml_simulation_profiled(
progress_callback=report_system_progress,
cancel_check=cancel_check,
activity_tracker=activity_tracker,
raw_series=raw_series,
)
except SimulationPreparationError as exc:
raise HTTPException(
@@ -799,7 +808,7 @@ def _run_system_xml_simulation_profiled(
"validation": report.as_dict(),
"simulation": document.as_model_data()["simulation"],
"model": network.as_interface_dict(),
**result.as_dict(),
**result.as_dict(raw_series=raw_series),
}
@@ -807,7 +816,8 @@ def simulation_event_stream(
xml_bytes: bytes,
*,
task: SimulationTaskRecord | None = None,
) -> Iterator[str]:
raw_series: bool = False,
) -> Iterator[str | bytes]:
events: queue.Queue[dict[str, object] | object] = queue.Queue()
finished = object()
latest_progress = 0
@@ -857,6 +867,7 @@ def simulation_event_stream(
emit_progress,
task.cancel_event.is_set if task is not None else None,
activity_tracker,
**({"raw_series": True} if raw_series else {}),
)
if task is not None:
result = _mark_simulation_task_result(task, result)
@@ -958,7 +969,11 @@ def simulation_event_stream(
continue
if event is finished:
break
yield json.dumps(event, ensure_ascii=False, separators=(",", ":")) + "\n"
if raw_series and isinstance(event, dict) and event.get("event") == "result":
yield from serialize_result_parts(event)
yield b"\n"
else:
yield json.dumps(event, ensure_ascii=False, separators=(",", ":")) + "\n"
finally:
if task is not None:
_request_simulation_task_cancel(task, "stalled")