Skip to content

Compute each distinct dielectric sheet once (same output) - #34

Merged
midub merged 3 commits into
masterfrom
perf/dielectric-sheets
Oct 8, 2026
Merged

midub merged 3 commits into
masterfrom
perf/dielectric-sheets

Conversation

@midub

@midub midub commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

Problem

testcase1-RevC-full (IPC consortium Testcase1, 58 MB XML) has 11 dielectric layers. Each sheet is the outline minus the holes that cross it, and with only through holes all 11 are identical (7.0 MB each, 4.2 M of 17.25 M triangles). The converter cut, triangulated and extruded each one separately: in WASM "cut and sheets" took 1.2–1.3 s and "extrude" 0.9 s of a 5.4–6 s conversion (perf-findings.md).

What this PR does (no profile change, same output)

  • One sheet per set of crossing drills. Layers crossed by the same drills (through() as before; drills that don't cross a layer don't count) have the same cuts. Each dielectric whose set matches an earlier dielectric's gets no sheet of its own in "cut and sheets"; in "extrude" it takes the earlier dielectric's mesh moved to its own heights.
  • LayerMesh::restacked(from, to) (boardui-geom): moves a mesh of extruded regions from heights from to to. Extrusion writes exactly two heights (z_min as f32 for bottom vertices, z_max as f32 for top ones), and triangulation doesn't depend on them, so the result is exactly the mesh that extruding at to gives (positions, indices, feature ranges and bounds). It returns None when either range is one extrusion rejects or the source heights coincide in f32; then, and when the first sheet failed to mesh (so the warning names the right layer), the pipeline extrudes the sheet again as before. Unit test plus a proptest (restacked == extruded again, including ranges that collapse in f32).
  • Other repeated work, the cheap and safe parts: copper and paste layers crossed by the same drills share one HoleCutter (R-tree), built once per set instead of once per layer, and the per-layer hole cuts are no longer cloned for the soldermask and dielectric unions (they take references, in the same order). Soldermask sheets can't be shared (each side has its own openings), and a shared hole union would change the boolean operations' input order and so the output bytes, so I left those alone.

Output: byte for byte the same

  • master's output is deterministic: two conformance runs (all 41 samples incl. the 5 fetched IPC test cases) and two CLI runs on testcase1-RevC-full gave identical GLBs, also identical to the 277,164,204-byte GLB from the analysis (master d9e1aa9).
  • This branch writes byte-identical GLBs for all 41 conformance samples (BOARDUI_CONFORMANCE_OUT, cmp) and for testcase1-RevC-full (CLI). No snapshot changes.
  • Why the measurement hack's output differed: it replaced v[2] (glTF z, i.e. −board y) instead of v[1] (board height), so its copied sheets were flattened, not moved.

Sharing per sample (sets of crossing drills = distinct sheet geometries, checked from the GLBs): testcase1-RevC-full 11 dielectrics → 1 sheet; blind-buried-vias (KiCad, blind and buried vias) 23 → 3; testcase11-rdgflx-RevC-full 5 → 2; royalblue54l-feather 7 → 1; IPC-2581-8-Layer-Design 7 → 1; fomu-pvt 3 → 3.

Numbers (testcase1-RevC-full)

docker-server (8 cores), master b6932ae vs this branch, alternating runs, medians. The machine is shared with other sessions; this series ran at load average 6–8 (an earlier one at 5–7 gave the same picture: WASM cut and sheets 1.29 → 0.84 s, extrude 0.93 → 0.67 s).

WASM (Node 24, packages/converter dist + wasm-bindgen output, no wasm-opt; first conversion in a fresh process; n = 7):

step master this PR
total 5.66 s 5.06 s (−0.60 s)
cut and sheets 1.22 s 0.84 s
extrude 0.89 s 0.69 s
resolve (unchanged) 1.50 s 1.53 s
WASM memory after conversion 1,315 MB 1,282 MB

Native CLI (release, rayon; n = 14): total wall 1.50 → 1.43 s, cut and sheets 0.204 → 0.150 s, extrude 0.153 → 0.135 s, peak memory 1,397 → 1,312 MB. Native gains less: the 11 sheets were cut in parallel there already.

Blind/buried vias: blind-buried-vias (KiCad sample, 23 dielectrics → 3 sheets) is tiny (48 ms in WASM either way, "cut and sheets" 3 → 2 ms). testcase11-rdgflx-RevC-full (5 → 2): WASM 0.49 → 0.44 s (median of 5), "cut and sheets" 28 → 18 ms.

Test evidence

In boardui-dev:1: cargo fmt --all --check, cargo clippy --workspace --all-targets --locked -- -D warnings, BOARDUI_REQUIRE_IPC_TESTCASES=1 cargo test --workspace --locked (conformance 51/51 with the fetched IPC test cases), cargo build -p boardui-wasm --target wasm32-unknown-unknown --release --locked: all pass. No packages/ changes.

Spec changes

None.

Known gaps / follow-ups

  • The file is unchanged, so the GLB still holds 11 copies of the sheet (77 MB of 277 MB): Identical dielectric sheets share one mesh (profile 0.10) #35 (stacked on this branch) lets identical sheets share one mesh (profile 0.10, 277 → 203 MB). It removes LayerMesh::restacked again, since nothing moves meshes once they're shared; if only this PR is merged, it stays.
  • The rest of "cut and sheets" is cutting holes out of the copper planes and the two soldermask sheets; "resolve" (1.6 s in WASM) is now the biggest step.

midub added 3 commits October 7, 2026 15:12
Dielectrics crossed by the same drills get the same sheet: cut and extrude it once
and move the mesh to the other dielectrics' heights (LayerMesh::restacked). Copper
and paste layers crossed by the same drills share one hole cutter, and hole cuts are
no longer cloned per layer. The GLB stays byte-for-byte the same.
@CLAassistant

CLAassistant commented Oct 7, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@midub
midub marked this pull request as ready for review October 7, 2026 16:33
@midub
midub merged commit a5830df into master Oct 8, 2026
5 checks passed
@midub
midub deleted the perf/dielectric-sheets branch October 8, 2026 12:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants