@jbroll/jscad-modeling 2.13.2 → 2.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/bench/compare-branches.sh +131 -0
  2. package/bench/compare-perf-branches.sh +126 -0
  3. package/bench/results/archive/base.txt +6 -0
  4. package/bench/results/archive/extrude.txt +6 -0
  5. package/bench/results/archive/flatten.txt +6 -0
  6. package/bench/results/archive/object-pooling.txt +6 -0
  7. package/bench/results/archive/polygontree.txt +6 -0
  8. package/bench/results/archive/splitpolygon.txt +6 -0
  9. package/bench/results/archive/summary.txt +26 -0
  10. package/bench/results/base-new.txt +12 -0
  11. package/bench/results/base.txt +6 -0
  12. package/bench/results/extrude-new.txt +12 -0
  13. package/bench/results/extrude.txt +6 -0
  14. package/bench/results/flatten-new.txt +12 -0
  15. package/bench/results/flatten.txt +6 -0
  16. package/bench/results/master-new.txt +12 -0
  17. package/bench/results/object-pooling-new.txt +12 -0
  18. package/bench/results/object-pooling.txt +6 -0
  19. package/bench/results/perf-optimization-analysis.md +80 -0
  20. package/bench/results/polygontree-new.txt +12 -0
  21. package/bench/results/polygontree.txt +6 -0
  22. package/bench/results/splitpolygon-new.txt +12 -0
  23. package/bench/results/splitpolygon.txt +6 -0
  24. package/bench/results/summary.txt +26 -0
  25. package/benchmarks/compare-branches.js +419 -0
  26. package/benchmarks/quick-timing.js +219 -0
  27. package/dist/jscad-modeling.min.js +165 -162
  28. package/package.json +1 -1
  29. package/src/index.js +1 -0
  30. package/src/operations/booleans/index.js +2 -2
  31. package/src/operations/minkowski/index.d.ts +0 -2
  32. package/src/operations/minkowski/minkowskiSum.js +40 -37
  33. package/src/operations/minkowski/minkowskiSum.test.js +44 -6
  34. package/src/operations/booleans/intersectMenger.test.js +0 -154
  35. package/src/operations/booleans/minkowski.js +0 -223
@@ -0,0 +1,131 @@
1
+ #!/bin/bash
2
+ #
3
+ # Compare performance across optimization branches
4
+ # Usage: ./compare-branches.sh
5
+ #
6
+
7
+ set -e
8
+
9
+ BASE_COMMIT="93d5df5d"
10
+ BRANCHES=(
11
+ "origin/pr/upstream-perf-polygontree"
12
+ "origin/pr/upstream-perf-splitpolygon"
13
+ "origin/pr/upstream-perf-flatten"
14
+ "origin/pr/upstream-perf-object-pooling"
15
+ "origin/pr/upstream-perf-extrude"
16
+ )
17
+
18
+ RESULTS_DIR="bench/results"
19
+ BENCH_BACKUP="/tmp/jscad-bench-$$"
20
+ mkdir -p "$RESULTS_DIR"
21
+
22
+ # Save current state
23
+ ORIGINAL_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || git rev-parse HEAD)
24
+ echo "Saving current state: $ORIGINAL_BRANCH"
25
+
26
+ # Backup bench scripts (they may not exist in base commit)
27
+ echo "Backing up bench scripts to $BENCH_BACKUP"
28
+ cp -r bench "$BENCH_BACKUP"
29
+
30
+ cleanup() {
31
+ echo ""
32
+ echo "Restoring original state: $ORIGINAL_BRANCH"
33
+ git checkout -f -q "$ORIGINAL_BRANCH" 2>/dev/null || git checkout -f -q -
34
+ # Restore bench scripts
35
+ cp -r "$BENCH_BACKUP"/* bench/ 2>/dev/null || true
36
+ rm -rf "$BENCH_BACKUP"
37
+ }
38
+ trap cleanup EXIT
39
+
40
+ checkout_and_restore() {
41
+ local ref="$1"
42
+ # Remove bench scripts but keep results
43
+ rm -f bench/*.js bench/*.sh 2>/dev/null || true
44
+ git checkout -f -q "$ref"
45
+ # Restore bench scripts
46
+ mkdir -p bench
47
+ cp "$BENCH_BACKUP"/*.js "$BENCH_BACKUP"/*.sh bench/ 2>/dev/null || true
48
+ }
49
+
50
+ run_benchmarks() {
51
+ local name="$1"
52
+ local outfile="$RESULTS_DIR/${name}.txt"
53
+
54
+ echo "Running benchmarks for: $name"
55
+ echo "=== $name ===" > "$outfile"
56
+ echo "" >> "$outfile"
57
+
58
+ # Run boolean benchmarks (most affected by optimizations)
59
+ echo "--- booleans.bench.js ---" >> "$outfile"
60
+ node bench/booleans.bench.js 2>&1 >> "$outfile"
61
+
62
+ echo "" >> "$outfile"
63
+ echo "--- splitPolygon.bench.js ---" >> "$outfile"
64
+ node --expose-gc bench/splitPolygon.bench.js 2>&1 >> "$outfile"
65
+
66
+ echo " -> Saved to $outfile"
67
+ }
68
+
69
+ echo "============================================================"
70
+ echo "Performance Comparison: Base vs Optimization Branches"
71
+ echo "============================================================"
72
+ echo ""
73
+ echo "Base commit: $BASE_COMMIT"
74
+ echo "Branches to test: ${#BRANCHES[@]}"
75
+ echo ""
76
+
77
+ # Run on base commit
78
+ echo "------------------------------------------------------------"
79
+ echo "[1/$((${#BRANCHES[@]}+1))] Checking out BASE: $BASE_COMMIT"
80
+ echo "------------------------------------------------------------"
81
+ checkout_and_restore "$BASE_COMMIT"
82
+ run_benchmarks "base"
83
+ echo ""
84
+
85
+ # Run on each optimization branch
86
+ i=2
87
+ for branch in "${BRANCHES[@]}"; do
88
+ short_name=$(echo "$branch" | sed 's|origin/pr/upstream-perf-||')
89
+ echo "------------------------------------------------------------"
90
+ echo "[$i/$((${#BRANCHES[@]}+1))] Checking out: $short_name"
91
+ echo "------------------------------------------------------------"
92
+ checkout_and_restore "$branch"
93
+ run_benchmarks "$short_name"
94
+ echo ""
95
+ ((i++))
96
+ done
97
+
98
+ echo "============================================================"
99
+ echo "All benchmarks complete. Results in $RESULTS_DIR/"
100
+ echo "============================================================"
101
+ echo ""
102
+
103
+ # Generate comparison summary
104
+ echo "Generating comparison summary..."
105
+ echo ""
106
+ echo "=== COMPARISON SUMMARY ===" | tee "$RESULTS_DIR/summary.txt"
107
+ echo "" | tee -a "$RESULTS_DIR/summary.txt"
108
+
109
+ # Extract key metrics from each result file
110
+ for result in "$RESULTS_DIR"/*.txt; do
111
+ name=$(basename "$result" .txt)
112
+ [[ "$name" == "summary" ]] && continue
113
+
114
+ echo "--- $name ---" | tee -a "$RESULTS_DIR/summary.txt"
115
+
116
+ # Extract torus(32) union time (good stress test metric)
117
+ torus_time=$(grep "union: torus(32)" "$result" | awk '{print $4}')
118
+ if [[ -n "$torus_time" ]]; then
119
+ echo " union torus(32)+torus(32): ${torus_time} ms/op" | tee -a "$RESULTS_DIR/summary.txt"
120
+ fi
121
+
122
+ # Extract spanning split time
123
+ spanning_time=$(grep "spanning split.*quad" "$result" | awk '{print $6}')
124
+ if [[ -n "$spanning_time" ]]; then
125
+ echo " spanning split (quad): ${spanning_time} µs/op" | tee -a "$RESULTS_DIR/summary.txt"
126
+ fi
127
+
128
+ echo "" | tee -a "$RESULTS_DIR/summary.txt"
129
+ done
130
+
131
+ echo "Done! See $RESULTS_DIR/summary.txt for quick comparison."
@@ -0,0 +1,126 @@
1
+ #!/bin/bash
2
+ #
3
+ # Compare performance across optimization branches using standardized benchmarks
4
+ #
5
+ # Usage: ./compare-perf-branches.sh [runs]
6
+ #
7
+
8
+ set -e
9
+
10
+ MODELING_DIR="/home/john/pkg/OpenJSCAD.org/packages/modeling"
11
+ BENCHMARK_RUNNER="/home/john/src/jscadui/apps/jscad-web/run-benchmarks.cjs"
12
+
13
+ BASE_COMMIT="93d5df5d"
14
+ BRANCHES=(
15
+ "origin/pr/upstream-perf-polygontree"
16
+ "origin/pr/upstream-perf-splitpolygon"
17
+ "origin/pr/upstream-perf-flatten"
18
+ "origin/pr/upstream-perf-object-pooling"
19
+ "origin/pr/upstream-perf-extrude"
20
+ )
21
+
22
+ # Key benchmarks that stress boolean operations
23
+ BENCHMARKS="sphere-union,swiss-cheese,chainmail,menger-intersect,sphere-cloud"
24
+
25
+ RUNS="${1:-3}"
26
+ RESULTS_DIR="$MODELING_DIR/bench/results"
27
+ mkdir -p "$RESULTS_DIR"
28
+
29
+ cd "$MODELING_DIR"
30
+
31
+ # Save current state
32
+ ORIGINAL_REF=$(git rev-parse HEAD)
33
+ echo "Saving current state: $ORIGINAL_REF"
34
+
35
+ cleanup() {
36
+ echo ""
37
+ echo "Restoring original state..."
38
+ git checkout -f -q "$ORIGINAL_REF" 2>/dev/null || true
39
+ }
40
+ trap cleanup EXIT
41
+
42
+ run_benchmarks() {
43
+ local name="$1"
44
+ local outfile="$RESULTS_DIR/${name}.txt"
45
+
46
+ echo "=== $name ===" > "$outfile"
47
+
48
+ # Run each key benchmark
49
+ for bench in ${BENCHMARKS//,/ }; do
50
+ result=$(node "$BENCHMARK_RUNNER" "$bench" "$RUNS" "$MODELING_DIR" 2>&1 | grep "benchmark-" | awk '{print $2}')
51
+ echo "$bench $result" >> "$outfile"
52
+ done
53
+ }
54
+
55
+ echo "============================================================"
56
+ echo "Performance Comparison: Base vs Optimization Branches"
57
+ echo "============================================================"
58
+ echo ""
59
+ echo "Modeling dir: $MODELING_DIR"
60
+ echo "Base commit: $BASE_COMMIT"
61
+ echo "Runs: $RUNS"
62
+ echo "Benchmarks: $BENCHMARKS"
63
+ echo ""
64
+
65
+ # Run on base commit
66
+ echo "------------------------------------------------------------"
67
+ echo "[1/$((${#BRANCHES[@]}+1))] BASE: $BASE_COMMIT"
68
+ echo "------------------------------------------------------------"
69
+ git checkout -f -q "$BASE_COMMIT"
70
+ run_benchmarks "base"
71
+ cat "$RESULTS_DIR/base.txt"
72
+ echo ""
73
+
74
+ # Run on each optimization branch
75
+ i=2
76
+ for branch in "${BRANCHES[@]}"; do
77
+ short_name=$(echo "$branch" | sed 's|origin/pr/upstream-perf-||')
78
+ echo "------------------------------------------------------------"
79
+ echo "[$i/$((${#BRANCHES[@]}+1))] $short_name"
80
+ echo "------------------------------------------------------------"
81
+ git checkout -f -q "$branch"
82
+ run_benchmarks "$short_name"
83
+ cat "$RESULTS_DIR/${short_name}.txt"
84
+ echo ""
85
+ ((i++))
86
+ done
87
+
88
+ echo "============================================================"
89
+ echo "COMPARISON TABLE"
90
+ echo "============================================================"
91
+ echo ""
92
+
93
+ # Print header
94
+ printf "%-16s" "Benchmark"
95
+ printf "%10s" "base"
96
+ for branch in "${BRANCHES[@]}"; do
97
+ short=$(echo "$branch" | sed 's|origin/pr/upstream-perf-||')
98
+ printf "%10s" "$short"
99
+ done
100
+ echo ""
101
+ printf "%-16s" "--------"
102
+ printf "%10s" "----"
103
+ for branch in "${BRANCHES[@]}"; do
104
+ printf "%10s" "----"
105
+ done
106
+ echo ""
107
+
108
+ # Print data rows
109
+ for bench in ${BENCHMARKS//,/ }; do
110
+ printf "%-16s" "$bench"
111
+ # Base time
112
+ base_time=$(grep "^$bench " "$RESULTS_DIR/base.txt" | awk '{print $2}')
113
+ printf "%10s" "$base_time"
114
+
115
+ # Branch times
116
+ for branch in "${BRANCHES[@]}"; do
117
+ short=$(echo "$branch" | sed 's|origin/pr/upstream-perf-||')
118
+ time=$(grep "^$bench " "$RESULTS_DIR/${short}.txt" | awk '{print $2}')
119
+ printf "%10s" "$time"
120
+ done
121
+ echo ""
122
+ done
123
+
124
+ echo ""
125
+ echo "Times in milliseconds (lower is better)"
126
+ echo "Results saved to: $RESULTS_DIR/"
@@ -0,0 +1,6 @@
1
+ === base ===
2
+ sphere-union 612.9
3
+ swiss-cheese 108.4
4
+ chainmail 525.2
5
+ menger-intersect 28.7
6
+ sphere-cloud 235.5
@@ -0,0 +1,6 @@
1
+ === extrude ===
2
+ sphere-union 565.3
3
+ swiss-cheese 103.3
4
+ chainmail 575.9
5
+ menger-intersect 25.8
6
+ sphere-cloud 269.6
@@ -0,0 +1,6 @@
1
+ === flatten ===
2
+ sphere-union 633.9
3
+ swiss-cheese 119.9
4
+ chainmail 1198.7
5
+ menger-intersect 22.3
6
+ sphere-cloud 202.0
@@ -0,0 +1,6 @@
1
+ === object-pooling ===
2
+ sphere-union 541.2
3
+ swiss-cheese 239.1
4
+ chainmail 884.4
5
+ menger-intersect 18.9
6
+ sphere-cloud 195.8
@@ -0,0 +1,6 @@
1
+ === polygontree ===
2
+ sphere-union 601.7
3
+ swiss-cheese 106.0
4
+ chainmail 593.4
5
+ menger-intersect 28.9
6
+ sphere-cloud 242.4
@@ -0,0 +1,6 @@
1
+ === splitpolygon ===
2
+ sphere-union 587.7
3
+ swiss-cheese 126.1
4
+ chainmail 1363.3
5
+ menger-intersect 22.2
6
+ sphere-cloud 230.1
@@ -0,0 +1,26 @@
1
+ === COMPARISON SUMMARY ===
2
+
3
+ --- base ---
4
+ union torus(32)+torus(32): torus(32) ms/op
5
+ spanning split (quad): quad µs/op
6
+
7
+ --- extrude ---
8
+ union torus(32)+torus(32): torus(32) ms/op
9
+ spanning split (quad): quad µs/op
10
+
11
+ --- flatten ---
12
+ union torus(32)+torus(32): torus(32) ms/op
13
+ spanning split (quad): quad µs/op
14
+
15
+ --- object-pooling ---
16
+ union torus(32)+torus(32): torus(32) ms/op
17
+ spanning split (quad): quad µs/op
18
+
19
+ --- polygontree ---
20
+ union torus(32)+torus(32): torus(32) ms/op
21
+ spanning split (quad): quad µs/op
22
+
23
+ --- splitpolygon ---
24
+ union torus(32)+torus(32): torus(32) ms/op
25
+ spanning split (quad): quad µs/op
26
+
@@ -0,0 +1,12 @@
1
+ ════════════════════════════════════════════════════════════
2
+ Quick Benchmark Timing (heavy mode)
3
+ ════════════════════════════════════════════════════════════
4
+
5
+ swiss-cheese 31.18s
6
+ sphere-union 33.42s
7
+ sphere-cloud 26.82s
8
+ menger-intersect 25.53s
9
+ chainmail 22.86s
10
+ ────────────────────────────────
11
+ TOTAL 139.81s
12
+
@@ -0,0 +1,6 @@
1
+ === base ===
2
+ sphere-union 612.9
3
+ swiss-cheese 108.4
4
+ chainmail 525.2
5
+ menger-intersect 28.7
6
+ sphere-cloud 235.5
@@ -0,0 +1,12 @@
1
+ ════════════════════════════════════════════════════════════
2
+ Quick Benchmark Timing (heavy mode)
3
+ ════════════════════════════════════════════════════════════
4
+
5
+ swiss-cheese 25.24s
6
+ sphere-union 32.29s
7
+ sphere-cloud 31.38s
8
+ menger-intersect 24.88s
9
+ chainmail 38.30s
10
+ ────────────────────────────────
11
+ TOTAL 152.09s
12
+
@@ -0,0 +1,6 @@
1
+ === extrude ===
2
+ sphere-union 565.3
3
+ swiss-cheese 103.3
4
+ chainmail 575.9
5
+ menger-intersect 25.8
6
+ sphere-cloud 269.6
@@ -0,0 +1,12 @@
1
+ ════════════════════════════════════════════════════════════
2
+ Quick Benchmark Timing (heavy mode)
3
+ ════════════════════════════════════════════════════════════
4
+
5
+ swiss-cheese 27.92s
6
+ sphere-union 27.01s
7
+ sphere-cloud 28.25s
8
+ menger-intersect 31.02s
9
+ chainmail 89.45s
10
+ ────────────────────────────────
11
+ TOTAL 203.66s
12
+
@@ -0,0 +1,6 @@
1
+ === flatten ===
2
+ sphere-union 633.9
3
+ swiss-cheese 119.9
4
+ chainmail 1198.7
5
+ menger-intersect 22.3
6
+ sphere-cloud 202.0
@@ -0,0 +1,12 @@
1
+ ════════════════════════════════════════════════════════════
2
+ Quick Benchmark Timing (heavy mode)
3
+ ════════════════════════════════════════════════════════════
4
+
5
+ swiss-cheese 24.93s
6
+ sphere-union 25.32s
7
+ sphere-cloud 15.51s
8
+ menger-intersect 7.52s
9
+ chainmail 9.62s
10
+ ────────────────────────────────
11
+ TOTAL 82.90s
12
+
@@ -0,0 +1,12 @@
1
+ ════════════════════════════════════════════════════════════
2
+ Quick Benchmark Timing (heavy mode)
3
+ ════════════════════════════════════════════════════════════
4
+
5
+ swiss-cheese 23.33s
6
+ sphere-union 25.65s
7
+ sphere-cloud 25.16s
8
+ menger-intersect 23.30s
9
+ chainmail 44.90s
10
+ ────────────────────────────────
11
+ TOTAL 142.34s
12
+
@@ -0,0 +1,6 @@
1
+ === object-pooling ===
2
+ sphere-union 541.2
3
+ swiss-cheese 239.1
4
+ chainmail 884.4
5
+ menger-intersect 18.9
6
+ sphere-cloud 195.8
@@ -0,0 +1,80 @@
1
+ # Performance Optimization Analysis
2
+
3
+ **Date:** 2026-02-06
4
+ **Base commit:** 93d5df5d
5
+ **Branches analyzed:** origin/pr/upstream-perf-*
6
+
7
+ ## Summary
8
+
9
+ Five performance optimization branches were analyzed. When combined on master, they produce a **3-4x speedup** on complex boolean operations. Individual branches show less improvement due to remaining O(n²) bottlenecks and high benchmark variance.
10
+
11
+ ## Optimization Branches
12
+
13
+ | Branch | Optimization | Complexity Fix |
14
+ |--------|-------------|----------------|
15
+ | `splitpolygon` | Replace splice with filter in duplicate vertex removal | O(n²) → O(n) |
16
+ | `polygontree` | Defer PolygonTreeNode cleanup, avoid splice in remove() | O(n²) → O(1) |
17
+ | `flatten` | Iterative flatten with stack instead of recursive concat | O(n²) → O(n) |
18
+ | `extrude` | Replace concat with push in extrudeFromSlices | O(n²) → O(n) |
19
+ | `object-pooling` | Pre-allocate arrays in splitPolygonByPlane + O(n) fix | Reduces allocations |
20
+
21
+ ## Benchmark Results (Heavy Mode)
22
+
23
+ ### Chainmail Benchmark (36 tori union)
24
+
25
+ ```
26
+ Branch Time (3 runs) Variance
27
+ base 37.7s, 39.7s, 39.4s ±3% (consistent)
28
+ splitpolygon 39.1s, 37.9s, 60.6s ±37% (variable)
29
+ object-pooling 17.8s, 23.7s, 55.2s ±68% (very variable)
30
+ master 9.5s, 12.1s, 14.1s ±19% (fast)
31
+ ```
32
+
33
+ ### Full Suite (Single Run)
34
+
35
+ ```
36
+ swiss-cheese sphere-union sphere-cloud menger chainmail TOTAL
37
+ base 31.2s 33.4s 26.8s 25.5s 22.9s 139.8s
38
+ splitpolygon 25.3s 26.7s 23.8s 21.6s 22.9s 120.3s
39
+ master 24.9s 25.3s 15.5s 7.5s 9.6s 82.9s
40
+ ```
41
+
42
+ ## Key Findings
43
+
44
+ 1. **High variance** - The chainmail benchmark shows up to 3x variance between runs on the same code. Single-run benchmarks are unreliable.
45
+
46
+ 2. **Synergistic optimizations** - Master (with all optimizations) achieves 3-4x speedup because fixing ALL O(n²) bottlenecks produces compounding benefits.
47
+
48
+ 3. **splitPolygonByPlane is the hot path** - This function is called thousands of times during complex boolean operations. The O(n²) splice in duplicate vertex removal was the primary bottleneck.
49
+
50
+ 4. **Individual branches don't show full benefit** - Each branch fixes one bottleneck while others remain, limiting observable improvement.
51
+
52
+ ## Recommended Push Order
53
+
54
+ 1. **splitpolygon** - Highest impact, minimal change, foundation for others
55
+ 2. **polygontree** - Independent O(n²) fix, high impact
56
+ 3. **flatten** - Independent O(n²) fix, moderate impact
57
+ 4. **extrude** - Independent optimization, lower impact
58
+ 5. **object-pooling** - Adds pooling on top of splitpolygon fix (push after #1)
59
+
60
+ ## Additional Optimizations on Master
61
+
62
+ These commits are on master but not in the upstream-perf branches:
63
+
64
+ - `3d6214b6` - poly3 V8 performance optimization
65
+ - `818a2a1a` - vec2 allocation reduction in reTesselateCoplanarPolygons
66
+
67
+ ## Files Changed
68
+
69
+ | Branch | Files Modified |
70
+ |--------|---------------|
71
+ | splitpolygon | `src/operations/booleans/trees/splitPolygonByPlane.js` |
72
+ | polygontree | `src/operations/booleans/trees/PolygonTreeNode.js` |
73
+ | flatten | `src/utils/flatten.js` |
74
+ | extrude | `src/operations/extrusions/extrudeFromSlices.js` |
75
+ | object-pooling | `src/operations/booleans/trees/splitPolygonByPlane.js` |
76
+
77
+ ## Benchmarking Tools
78
+
79
+ - `benchmarks/quick-timing.js` - Quick single-run timing (lite/heavy modes)
80
+ - `benchmarks/compare-branches.js` - Interleaved multi-run comparison between branches
@@ -0,0 +1,12 @@
1
+ ════════════════════════════════════════════════════════════
2
+ Quick Benchmark Timing (heavy mode)
3
+ ════════════════════════════════════════════════════════════
4
+
5
+ swiss-cheese 20.74s
6
+ sphere-union 25.81s
7
+ sphere-cloud 23.89s
8
+ menger-intersect 14.02s
9
+ chainmail 64.09s
10
+ ────────────────────────────────
11
+ TOTAL 148.55s
12
+
@@ -0,0 +1,6 @@
1
+ === polygontree ===
2
+ sphere-union 601.7
3
+ swiss-cheese 106.0
4
+ chainmail 593.4
5
+ menger-intersect 28.9
6
+ sphere-cloud 242.4
@@ -0,0 +1,12 @@
1
+ ════════════════════════════════════════════════════════════
2
+ Quick Benchmark Timing (heavy mode)
3
+ ════════════════════════════════════════════════════════════
4
+
5
+ swiss-cheese 25.27s
6
+ sphere-union 26.73s
7
+ sphere-cloud 23.81s
8
+ menger-intersect 21.60s
9
+ chainmail 22.92s
10
+ ────────────────────────────────
11
+ TOTAL 120.32s
12
+
@@ -0,0 +1,6 @@
1
+ === splitpolygon ===
2
+ sphere-union 587.7
3
+ swiss-cheese 126.1
4
+ chainmail 1363.3
5
+ menger-intersect 22.2
6
+ sphere-cloud 230.1
@@ -0,0 +1,26 @@
1
+ === COMPARISON SUMMARY ===
2
+
3
+ --- base ---
4
+ union torus(32)+torus(32): torus(32) ms/op
5
+ spanning split (quad): quad µs/op
6
+
7
+ --- extrude ---
8
+ union torus(32)+torus(32): torus(32) ms/op
9
+ spanning split (quad): quad µs/op
10
+
11
+ --- flatten ---
12
+ union torus(32)+torus(32): torus(32) ms/op
13
+ spanning split (quad): quad µs/op
14
+
15
+ --- object-pooling ---
16
+ union torus(32)+torus(32): torus(32) ms/op
17
+ spanning split (quad): quad µs/op
18
+
19
+ --- polygontree ---
20
+ union torus(32)+torus(32): torus(32) ms/op
21
+ spanning split (quad): quad µs/op
22
+
23
+ --- splitpolygon ---
24
+ union torus(32)+torus(32): torus(32) ms/op
25
+ spanning split (quad): quad µs/op
26
+