Align AXIS control flow and fix pause and program rendering
Document source UI gates, explicit native live-plot clearing, and remaining parity boundaries. Fix pause/resume transport continuity, repeated stepping, coordinate previews, and spindle override state. Optimize large program snapshots and rendering, and cover the control flows with native Tcl, WASM, and browser checks. Validation: 22 native tests and source/browser checks pass. Worker/App regression: 113 of 123 pass; 10 pre-existing failures remain documented with no new failures.
This commit is contained in:
56
scripts/benchmark_xyzac_program_replacement.mjs
Normal file
56
scripts/benchmark_xyzac_program_replacement.mjs
Normal file
@@ -0,0 +1,56 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFile } from "node:fs/promises";
|
||||
import createModule from "../build-wasm/linuxcnc-sim-core.js";
|
||||
import { loadSimulationCase, toWorkerConfiguration } from "../web/workspace/sim-case-loader.mjs";
|
||||
import { XyzacSession, CONTEXT_ID } from "../web/worker/xyzac-session.mjs";
|
||||
|
||||
const root = new URL("../", import.meta.url);
|
||||
const read = (path) => readFile(new URL(path, root), "utf8");
|
||||
const bundle = await loadSimulationCase({ path: "linuxcnc/configs/sim/axis/vismach/5axis/table-rotary-tilting/xyzac-trt.ini", fetchImpl: async (url) => {
|
||||
try { const body = await read(String(url).replace(/^\//, "")); return { ok: true, text: async () => body }; }
|
||||
catch { return { ok: false, text: async () => "" }; }
|
||||
} });
|
||||
const core = await createModule({ wasmBinary: await readFile(new URL("build-wasm/linuxcnc-sim-core.wasm", root)) });
|
||||
const session = new XyzacSession(core, { sessionId: "replacement-benchmark" });
|
||||
let seq = 0;
|
||||
const send = (kind, payload = {}) => {
|
||||
const result = session.accept({ schema_version: 1, context_id: CONTEXT_ID, session_id: session.sessionId, kind, payload, seq: ++seq, operation_id: `bench-${seq}` });
|
||||
assert.notEqual(result.kind, "ERROR", `${kind}: ${result.payload.gate_reason ?? result.payload.message_key}`);
|
||||
return result.payload;
|
||||
};
|
||||
send("HELLO"); send("SESSION_ATTACH"); send("LOAD_WORKSPACE", { root_path: "/workspace", configuration: toWorkerConfiguration(bundle) });
|
||||
send("PROGRAM_LOAD", { source: "G21 G90\nG0 X0 Y0 Z1\nG1 X1 F600\nG1 X0\nM2\n", path: "first.ngc" });
|
||||
send("POWER", { active: true }); send("HOME", { all: true }); send("PROGRAM_RUN");
|
||||
for (let n = 0; n < 1000 && session.task.state.state !== "STOPPED"; n++) send("SIM_STEP", { cycles: 5, response: "motion_delta" });
|
||||
assert.equal(session.task.state.state, "STOPPED");
|
||||
const path = "linuxcnc/nc_files/3D_Chips.ngc", source = await read(path);
|
||||
const ticks = Number(process.env.BENCH_TICKS ?? 200);
|
||||
const rows = [];
|
||||
for (let attempt = 1; attempt <= 2; attempt++) {
|
||||
const start = performance.now();
|
||||
const loaded = send("PROGRAM_LOAD", { source, path });
|
||||
const loadMs = performance.now() - start;
|
||||
const snapshotStart = performance.now();
|
||||
for (let sample = 0; sample < 200; sample++) session.xyzacProgram.snapshot();
|
||||
const snapshotMs = performance.now() - snapshotStart;
|
||||
send("PROGRAM_RUN");
|
||||
const runStart = performance.now();
|
||||
let result;
|
||||
const latencies = [];
|
||||
for (let tick = 0; tick < ticks; tick += 5) {
|
||||
const requestStart = performance.now();
|
||||
result = send("SIM_STEP", { cycles: 5, response: "motion_delta" });
|
||||
latencies.push(performance.now() - requestStart);
|
||||
}
|
||||
const runMs = performance.now() - runStart;
|
||||
const state = session.wasmMotion.read().state;
|
||||
rows.push({ attempt, load_ms: loadMs, snapshot_200_ms: snapshotMs, run_ms: runMs, task_ticks: ticks, simulated_ms: ticks * 10, p95_step_ms: latencies.sort((a, b) => a - b)[Math.floor(latencies.length * .95)], source_hash: loaded.program.source_hash, preview_hash: loaded.preview.preview_hash, preview_segments: loaded.preview.segments.length, final_line: result.program.current_line, pose: state.position, queue: state.queue_depth, feed: state.feed_override, velocity: state.velocity, live_epoch: loaded.panel_snapshot.visual.live_path_epoch });
|
||||
send("PROGRAM_ABORT");
|
||||
if (attempt === 1) {
|
||||
// Reset the machine position through the interpreter, preserving source
|
||||
// semantics, so the repeated load has the same physical starting point.
|
||||
send("MDI_EXECUTE", { block: "G90 G0 X0 Y0 Z1" });
|
||||
for (let tick = 0; tick < 2000 && session.wasmMotion.read().state.queue_depth; tick++) send("SIM_STEP", { cycles: 5, response: "motion_delta" });
|
||||
}
|
||||
}
|
||||
console.log(JSON.stringify({ schema: "xyzac-replacement-benchmark.v1", rows }));
|
||||
Reference in New Issue
Block a user