优化原生结果编码传输与浏览器缓存,记录八路性能基线
原生结果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:
1 parent
808c484f5b
commit
3bc4be3c06
55 files changed
+20522
-141
No files matched your search
+22
-7
@@ -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")
|
||||
|
||||
Reference in new issue
Block a user