Skip to content

perf: detect Mach-O via magic bytes and parallelize test suite#180

Merged
MarshallOfSound merged 4 commits intomainfrom
sam/perf-macho-detection-and-parallel-tests
Mar 16, 2026
Merged

perf: detect Mach-O via magic bytes and parallelize test suite#180
MarshallOfSound merged 4 commits intomainfrom
sam/perf-macho-detection-and-parallel-tests

Conversation

@MarshallOfSound
Copy link
Member

Summary

Two related performance passes — one on makeUniversalApp itself, one on the test suite.

Runtime

  • Mach-O detection: getAllAppFiles was spawning file --brief --no-pad for every file in the bundle. Replaced with a direct 8-byte header read + isMachO() check. Includes a disambiguation against Java .class files, which share the 0xCAFEBABE magic with Mach-O fat binaries — Mach-O stores nfat_arch in bytes 4-7 (small int), Java stores major_version >= 45.
  • APFS clone: try cp -cR for the x64→tmp staging copy (near-instant CoW on APFS), fall back to cp -R if it fails.
  • Resolve appPath via realpath before walking.

Tests

  • globalSetup builds fixture apps in parallel.
  • makeUniversalApp suite is now describe.concurrent; each test gets its own mkdtemp output dir (cleaned in afterAll), and expect is threaded through verifyApp/verifyFileTree/ensureUniversal so snapshots stay attributed correctly.
  • templateApp extracts into a unique temp dir to avoid concurrent races on the shared Electron.app intermediate path.
  • createStagingAppDir uses mkdtemp instead of Math.random()*100 suffixes.
  • maxConcurrency: 4 to keep the disk/CPU thrash bounded.

Test plan

  • yarn test passes locally
  • CI green
  • Spot-check a built universal app still launches on both arches

Runtime improvements:
- Replace `file --brief --no-pad` spawn-per-file with direct magic byte
  reads in getAllAppFiles. Adds isMachO() helper with disambiguation
  between Mach-O fat binaries and Java .class files (both 0xCAFEBABE;
  bytes 4-7 are nfat_arch for Mach-O, major/minor version for Java).
- Try APFS copy-on-write clone (cp -cR) when staging the x64 template,
  falling back to cp -R on non-APFS volumes.
- Resolve appPath through realpath before walking to avoid symlink edge
  cases.

Test suite improvements:
- Run fixture templateApp setup in parallel (globalSetup).
- Convert makeUniversalApp suite to describe.concurrent with per-test
  mkdtemp output dirs; pass ExpectStatic through helpers so snapshots
  attribute to the right test under concurrency.
- Extract Electron zip into a unique tmpdir in templateApp to avoid
  races on the intermediate Electron.app path.
- Use mkdtemp for staging app dirs instead of random-suffix collision
  avoidance.
- Cap maxConcurrency at 4.
@MarshallOfSound MarshallOfSound requested a review from a team as a code owner March 12, 2026 04:51
@electron/get is not safe for concurrent downloads of the same artifact.
On CI with a cold cache, the parallel templateApp calls in globalSetup
raced writing to the same cache path and produced a corrupt/missing zip.

Warm the cache for both archs serially in globalSetup before any parallel
work starts; all subsequent templateApp calls (in globalSetup and in the
concurrent test suite) then hit the cached zip.
@MarshallOfSound MarshallOfSound force-pushed the sam/perf-macho-detection-and-parallel-tests branch from a6b2915 to 43801fb Compare March 12, 2026 05:02
@MarshallOfSound MarshallOfSound merged commit eeea66f into main Mar 16, 2026
4 checks passed
@MarshallOfSound MarshallOfSound deleted the sam/perf-macho-detection-and-parallel-tests branch March 16, 2026 18:18
@electron-npm-package-publisher

🎉 This PR is included in version 3.0.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants