Conversation
…boolean A hinge part with four 36-tooth serration rings (patternCircular) took minutes to evaluate. A CPU profile of one ring: 92% of the time was in fusePatternInstances, and it split evenly between the BRepAlgoAPI_Fuse_3 constructor and BRepAlgoAPI_BooleanOperation::Build. 1. Every history-aware boolean ran twice. The shape-taking constructors (BRepAlgoAPI_Fuse_3, _Cut_3, _Common_3) already run the operation; the explicit Build() after SetToFillHistory ran all of it again. runBooleanWithHistory now default-constructs the builder, sets the arguments, tools and history flag, and builds once. This halves the cost of every union, subtract and intersect. 2. The pattern lowerer folded N instances with N-1 pairwise fuses, each against the growing accumulator. It now fuses all instances in ONE general-fuse build (fuseManyWithHistory). Per-instance lineage retags are kept; mergeBooleanHistoryMany applies input maps in order, so the first input wins a shared face, the same as the pairwise fold. Reproduction part, CLI on this Mac (machine under other load; wall times vary): evaluate 118-203 s -> 47-103 s, export stl --parts all 145 s -> 39 s, export step 177 s -> 58-60 s. Output is unchanged: the same volume, surface area, bbox and triangle count per part, both STLs watertight, and the STEP file is the same size. Test: tests/unit/backends/occt/patternBooleanCost.test.ts counts OCCT builds (not wall time). On the old code a 12-instance circular pattern costs 22 builds, a 5-instance linear pattern 8, one pairwise fuse 2. Now each costs 1. A serration-ring case checks the volume, bbox and solid count of the one-shot fuse. Signed-off-by: Andrii Shylenko <14119286+w1ne@users.noreply.github.com>
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Evaluating a real part (a hinge with four 36-tooth
patternCircularserration rings) took 6-10 minutes hosted and about 2-3 minutes on a Mac. Hostedrender_previewthen went over the MCP client's 300 s limit.Root cause (measured)
A CPU profile of one 36-tooth ring showed 92% of the time in
fusePatternInstances. That time split evenly between two calls:constructor$BRepAlgoAPI_Fuse_3(30.0 s) andBRepAlgoAPI_BooleanOperation$Build(27.1 s).BRepAlgoAPI_Fuse_3/_Cut_3/_Common_3) already run the operation. TheBuild()call afterSetToFillHistory(true)then ran all of it again. This affects every union, subtract and intersect, not only patterns.Fix
runBooleanWithHistorydefault-constructs the builder, callsSetArguments,SetToolsandSetToFillHistory, then builds once.fuseManyWithHistory(body, tools[])runs one general-fuse build over all inputs. The pattern lowerer uses it. Per-instance lineage retags are kept.mergeBooleanHistoryManyapplies the input maps in order, so the first input wins a shared face, the same as the pairwise fold.booleanBuildStats.buildsis a deterministic cost probe for tests.Numbers
The reproduction part, run through the CLI built from this branch and from develop. Other jobs were loading the Mac (load average 18-30), so wall times vary.
The published
kernelcad@0.15.0on the same Mac took 146 s for evaluate, 104 s for STL and 83 s for STEP.Geometry is unchanged.
parts --jsongives the same volume (7834.9954 / 14632.1058 mm³), surface area, bbox and triangle count (13312 / 6698) for both parts. Both STLs are watertight. The STEP file is the same size (2149749 bytes).Tests
tests/unit/backends/occt/patternBooleanCost.test.tscounts OCCT builds, not wall time. On develop it fails: a 12-instance circular pattern costs 22 builds, a 5-instance linear pattern 8, and one pairwise fuse 2. On this branch each costs 1. A serration-ring case (teeth that touch along edges) checks the volume (= N × tooth), the bbox and the solid count. It passes on both develop and this branch, which shows the geometry is the same.Local runs: tests/unit/{backends,naming,patterns,kernel,modeling,compute,capture,intent} plus src/kernel and src/modeling, 2692 passed. The 7 failures are in
src/modeling/parts/*and fail the same way on develop:assets/partswas not generated locally.