Fix 40+ second simulator test setup delay#282
Merged
Conversation
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Environment.init() called mergeHeadInfo() synchronously, which runs `git fetch --deepen=1` on simulators. On CI simulators this fetch times out (~16s), blocking the entire test setup. Fix: remove mergeHeadInfo from Environment.init() and schedule it on instrumentationWorkQueue instead. setupCrashHandler() already waits for this queue before the session span is created, so the commit author/message metadata is still available when needed. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
…Info - Wrap all waitUntilAllOperationsAreFinished calls with Log.measure so queue drain time is visible in debug output - Add Environment.fetchMergeHeadInfo(log:) instance method that calls mergeHeadInfo and updates self.git, wrapped in Log.measure - Add DDTestMonitor.loadGitCommitInfo() that schedules fetchMergeHeadInfo on instrumentationWorkQueue — called from installTestMonitor, not gated by disableSourceLocation (commit metadata is unrelated to source location) Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Log.measure closures inside Environment.init that referenced the stored property `sourceRoot` caused "self captured before all members initialized". Introduce a local `sourceRootValue` binding and use it inside the closures. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
getJobId() expands /**/_diag globs by recursively scanning /Users/runner/actions-runner/, which on a CI machine can be a huge directory tree. Added a maxWildcardDepth=3 cap to expandGlobSegments so the ** wildcard stops expanding after 3 levels — the _diag directory is always 1-2 levels deep, so this preserves full functionality. Also add per-reader timing to env-ciReaders loop. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- mergeHeadInfo moves from instrumentationWorkQueue to gitUploadQueue (first operation); reference saved in mergeHeadOperation - gitStatusUpToDate (git subprocess) moves inside the upload operation so it no longer blocks test startup - uploadOp gets a dependency on mergeHeadOperation so env.git is fully populated before the upload runs - updateTracerConfig: when ITR does not require git upload, wait only for mergeHeadOperation (not the full queue) to get commit metadata Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Replace the collect-all-then-search approach in getJobId with a FileManager.searchGlob extension that short-circuits as soon as the first Worker_ log match is found. Key changes: - FileManagerExtensions.swift: new FileManager.searchGlob(_:maxWildcardDepth:body:) walks a glob pattern (supporting **) calling body on each matched directory; returns true and stops on the first body hit. ** with a tail only calls body on dirs matching the full subpath; ** as the last segment calls body on every dir in the subtree. Walking starts from the longest concrete prefix before the first **, not from /. - GithubCI.swift: getJobId iterates _diagnosticDirs lazily via searchGlob and returns as soon as a match is found, so specific dirs (no **) are checked before the broad ** patterns. - FileManagerExtensionsTests.swift + fixtures/glob/: 12 tests covering exact match, missing path, tail vs no-tail body-call semantics, early exit, depth capping, and scoped root. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
body returning nil means "keep going"; any non-nil value stops the walk and is returned directly, eliminating the need for callers to capture a mutable variable to carry the result. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
gnufede
approved these changes
Jun 16, 2026
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.
Summary
Diagnosed and fixed two root causes of a ~50s "Install Test Monitor" delay on iOS/tvOS/watchOS simulators (macOS native was unaffected).
Root cause 1:
Environment.initblocking ongit fetch(~16s)DDTestMonitor.envis a lazy static property. Its first access ininstallTestMonitor()triggeredEnvironment.init(), which synchronously calledmergeHeadInfo(). That function runsgit fetch --deepen=1to populate commit author/message metadata. On CI simulators with shallow clones or restricted network access, this fetch times out (~16s).Fix:
mergeHeadInfofromEnvironment.init()Environment.fetchMergeHeadInfo(log:)instance methodDDTestMonitor.loadGitCommitInfo()which schedules the fetch as the first operation ongitUploadQueueenv.gitis fully populated before uploadingupdateTracerConfigwaits formergeHeadOperationafter the settings response (full queue drain if ITR requires git upload, just the merge-head op otherwise)GitUploader.statusUpToDate(agit statussubprocess) into the queue operation so it no longer blocks startupRoot cause 2:
GithubCIEnvironmentReader.getJobIdscanning huge directory tree (~26s)GithubCIEnvironmentReader.read()callsgetJobId()which expands/**/_diagglob patterns by recursively walking/Users/runner/actions-runner/. On a CI machine this directory tree can be very large, causingFileManager.contentsOfDirectoryto iterate thousands of entries.Fix: Added a
maxWildcardDepth=3cap toexpandGlobSegments. The_diagdirectory is always 1–2 levels deep, so all legitimate paths are still found.Additional improvements
Log.measuretiming around allwaitUntilAllOperationsAreFinished()calls (instrumentationWorkQueue drain,gitUploadQueue drain,testOptimizationSetupQueue drain)Environment.init(env-testBundle,env-parallelizationDisabled,env-deviceInfo,env-ciReaders,env-gitInfoAt, etc.)mergeHeadInfowrapped inLog.measuregitStatusUpToDatewrapped inLog.measureTest plan
setupCrashHandler)requireGit)🤖 Generated with Claude Code