A task appears to stall, or work seems to run on an unexpected executor.
Fastest useful approach: use the Swift Executors instrument to record the same reproducible action, inspect task and executor activity, then verify any theory against code and app behavior. A trace narrows the search; it does not prove the root cause.
This guide is for independent developers and small teams investigating Swift Task, Main Actor, or executor behavior in an iOS or macOS app.
You’ll follow a repeatable path from symptom to trace and back to a code-level check.
Last updated October 27, 2026. The feature and environment notes were checked against Apple’s Xcode 27 release notes, current Xcode system requirements, and Apple’s Instruments command-line tool reference. Confirm the exact interface and supported environment in the Xcode version you use.
SECTION 01 Before recording: turn the symptom into a test
“Concurrency is broken” is not a useful recording condition. It combines distinct problems: a task may not start when expected, work may be scheduled differently from your assumption, or the interface may appear unresponsive while the underlying cause lies elsewhere.
First, describe the user-visible behavior in a way you can reproduce. For example, identify the screen or action, the data state, and the point at which the delay or unexpected result occurs. Keep the steps consistent between recordings. If the issue only occurs after a particular request, navigation sequence, or state change, include that condition rather than recording an unrelated app launch.
Next, decide what you need the trace to help you inspect:
- Task lifecycle: whether relevant asynchronous work appears to start, continue, or finish around the symptom.
- Executor activity: where work appears to be scheduled, including activity associated with the Main Actor or a custom executor when the installed tool version exposes it.
- Main execution path: what is happening around the user-visible stall, and whether the trace gives you a useful point to inspect in the code.
These are observation goals, not diagnoses. A delay that overlaps with executor activity does not by itself show that the executor caused the delay. Likewise, a quiet-looking interval is not proof that a task is deadlocked. Record the symptom, the expected behavior, and the observable event that would make the trace useful.
What concurrency information can the Swift Executors instrument show? It can expose task and executor-related activity that helps you inspect the timing and relationships visible in a recording. The exact track names and detail available depend on the relevant Xcode and Instruments version; use Apple’s Xcode 27 release notes as the feature reference, then check the interface in your installed version.
SECTION 02 Environment check: confirm the tools can answer the question
Before opening a recording session, check that the project and analysis environment match the target you need to investigate. A successful build proves that the project compiled under that build setup. It does not prove that Instruments is ready to capture the behavior you care about, that the target can be launched in the intended way, or that the symbols you need will be available for inspection.
Check the Xcode version, Instruments availability, the SDK used by the project, and the operating system of the target environment. Apple’s Xcode system requirements are the authority for supported versions and compatibility. Don’t rely on a remembered requirement from another Xcode release: a tool update may change which systems it supports.
Then confirm that the app can run in the environment you intend to profile. Use the same build configuration and launch route you expect to use during investigation. If the app runs on a simulator or device in your normal workflow, make sure that target is available to the profiling setup rather than assuming that a successful compile makes it available automatically.
Prepare symbols and project context before recording. A trace can be much harder to connect to your source when the app’s relevant symbols are missing or the build differs from the one you’re investigating. Keep the source revision, build configuration, target, and any relevant runtime conditions with your notes. That context gives you a way to tell whether two recordings are genuinely comparable.
Apple’s Instruments command-line tool reference documents the supported command-line tooling. It can help you understand the available tooling surface, but don’t assume a command-line workflow exposes every interaction or display available in the Instruments app. When a feature or control is unclear, check the documentation for your installed release and confirm it in the actual interface.
SECTION 03 Capture: make every trace correspond to a known action
Open Instruments, select the Swift Executors instrument if it is available in your installed version, and choose the app or target you prepared. Start recording before the reproducible action, perform that action consistently, and stop once the relevant behavior has been captured. Avoid collecting a long, unfocused session if it makes the event you care about difficult to locate.
Keep the capture tied to a clear reproduction. If you change the app state, launch path, test data, or build between recordings, write that down. Those differences can affect what you see and can make a later comparison misleading.
Save the trace with enough context to identify what it contains. A practical filename or adjacent note can include the app and branch, the reproduction condition, the target environment, the Xcode version, and the time of the run. Record the relevant code revision and build configuration separately if your trace archive does not capture them. The goal is not elaborate paperwork; it is to make sure that, when you reopen the trace, you know what action produced it.
Apple’s WWDC 2026 Instruments analysis session is a useful official companion for understanding the analysis workflow. Treat its interface and examples as material to compare with your own installed version, not as proof that every project, target, or environment will expose identical tracks.
Recording discipline: If you cannot explain which user action produced a trace, it will be difficult to use that trace to test a specific concurrency hypothesis.
SECTION 04 Read the trace: separate tasks, executors, and symptoms
Start with the time interval around the reproduced behavior. Look for visible task activity and executor-related tracks that help you form a question about the code. The instrument’s value is that it makes selected runtime activity inspectable; it does not label a track as “the bug” or supply a complete causal explanation.
Keep these concepts separate while reading:
- A task represents asynchronous work in your program. Look at the activity visible in the trace and ask whether it relates to the action you reproduced.
- An executor is relevant to where and how work is scheduled. Executor-related activity can suggest where to inspect scheduling assumptions or actor isolation.
- A thread pool is not interchangeable with a task or an executor. Activity associated with a cooperative thread pool can provide context, but a track’s presence alone does not tell you that a worker is blocked or that the pool is at fault.
- The Main Actor is relevant when your question concerns work isolated to main-actor execution. A task associated with Main Actor activity is a clue to inspect, not an automatic explanation for a slow interface.
- The app symptom is what the user experiences. A timeline can help you locate related runtime activity, but it does not replace observing the actual UI, output, or test result.
Track names, relationships, and detail can vary by tool version. If a track you expect is absent, first check whether your installed version documents that observation and whether the target and recording setup support it. Apple’s Xcode 27 release notes describe the instrument’s scope; Apple’s Instruments tutorial on work executing in a background thread offers a related example of using trace evidence to examine execution context.
How do you find Main Actor-related tasks in Instruments? Use the Swift Executors trace to locate Main Actor-related activity if the installed version exposes it, then connect the time interval to the action you recorded. Follow the visible event into the relevant code and confirm the app behavior. If the expected track or label is not present, don’t infer that no Main Actor work occurred; verify feature support and recording conditions first.
A useful trace-reading note is brief: record the time interval, the track or activity you inspected, the related app action, and the code path you plan to check. This prevents a screenshot from becoming a conclusion without an explanation.
SECTION 05 Code investigation: turn a trace clue into a testable hypothesis
Once you have a suspicious interval, return to the code that could produce the observed behavior. Check the task creation and cancellation paths, actor annotations, calls that cross actor boundaries, and any custom executor logic relevant to the trace. The right checks depend on your app; don’t rewrite unrelated concurrency code just because it appears near a busy part of the timeline.
Ask whether the code and the trace support the same explanation. For example, if you suspect work is taking an unexpected path, identify the call or task boundary that should show that behavior. If you suspect main-thread work is delaying a response, compare the recorded interval with the UI symptom and inspect what executes in that path. If your hypothesis is that a task never completes, check its awaited operations, cancellation behavior, and any state required for completion.
A trace can expose a useful time window without revealing every cause. It may not show the full input that triggered a task, the app’s intended state transition, or all information needed to explain a result. Pair it with the smallest targeted code review or test that can distinguish your hypothesis from an alternative.
Can a Swift Executors trace prove the code root cause? No. It can support or challenge a hypothesis by showing activity visible to the instrument, but it is not an automatic root-cause detector. Confirm the suspected code path, reproduce the behavior, and use additional evidence when the trace cannot distinguish between possible explanations.
If the trace doesn’t answer your original question, adjust the investigation rather than stretching the evidence. Make the reproduction more specific, capture a different part of the user flow, or use another diagnostic method suited to the missing evidence. A trace that narrows the search but leaves uncertainty is still useful; a claim of certainty without corroboration is not.
SECTION 06 Decision point: choose the next step and repeat the investigation
Use the trace to decide what to do next, not to declare success. This comparison helps you choose whether to change the reproduction, inspect code, or collect another kind of evidence.
| What you observe | What it supports | Next action |
|---|---|---|
| Relevant task activity appears near the reproduced symptom | A candidate task or code path may relate to the behavior | Inspect that path and test a specific hypothesis |
| Main Actor-related activity appears in the interval | Main-actor execution is worth examining | Check the relevant isolation boundary and compare with the app’s visible response |
| Executor or thread-pool activity differs from your expectation | Your scheduling assumption may need review | Verify the assumption in code and confirm the relevant track is supported by your tool version |
| The needed activity is absent or ambiguous | The current recording may not answer the question | Check setup and feature support, then refine the reproduction or use complementary evidence |
| A code change appears to address the issue | The hypothesis may be correct, but the result remains unverified | Repeat the same reproduction and compare the behavior and relevant trace evidence |
After a change, record again using the same steps, target, and comparable run conditions. Compare the particular behavior you set out to investigate: whether the task reaches the expected point, whether the relevant execution path changes, and whether the user-visible symptom still occurs. If the environment or action changed, state that before interpreting the difference.
There is no universal percentage improvement that makes a concurrency fix correct. Define acceptance from the original symptom and the app’s intended behavior. Keep the Xcode version, target environment, build context, and reproduction notes with both traces so that another developer—or you at a later date—can repeat the check. If you change the reproduction as well as the code, treat the new trace as a different experiment rather than a clean before-and-after comparison.
For a local Mac, the advantage is direct control over your project and development environment. The trade-offs are hardware cost, storage and maintenance, and the need to keep that machine available when you want to repeat analysis. A shared or remote Mac can avoid buying a dedicated machine, but adds dependence on a network connection, remote access, and the conditions of the hosted environment. Neither setup guarantees a particular trace, device connection, or analysis result.
If your current setup is a borrowed Mac or a general-purpose machine, the real drawbacks may be limited availability, a different tool environment between sessions, or local storage already occupied by development assets. A rented Mac can be a more flexible option when you need a separate macOS environment to run Xcode and repeat your own analysis without purchasing another computer. Review VPSNIX Mac rental options against how often you need access and whether remote operation fits your workflow; check the VPSNIX Help Center for service and access details before deciding. If you need continuous, high-volume use or physical access to local hardware, compare those requirements with owning a Mac instead.