Optimize Swift code for iOS performance
Outcome
Turn a Swift cost question or known hot path into a semantics-preserving
correction, focused change, or benchmark with an explicit cost mechanism and
evidence proportionate to the decision and claim.
Prefer the largest reliable gain. Remove unnecessary work before tuning ARC,
dispatch, bounds checks, or generated instructions.
Read references selectively
- Read
references/methodology.md before researching sources, reviewing a hot
path, planning a change, or assigning a priority score.
- Read
references/cost-model-and-compiler.md for allocation, stack versus heap,
stored versus computed type properties, dispatch, generics, existentials,
closures, exclusivity, specialization, and build optimization.
- Read
references/ownership-and-memory.md for struct versus class decisions,
ARC, weak or unowned references, copy-on-write, slices, captures, bridging, or
long-lived shared storage.
- Read
references/collections-algorithms-and-text.md for algorithmic
complexity, capacity, collection choice, lazy pipelines, String, Substring,
Data, parsing, mapping, or formatter reuse.
- Read
references/concurrency-costs.md for task granularity, actor hops,
executor scheduling, continuations, task groups, or bounded parallelism.
- Read
references/benchmarking.md before writing a benchmark or claiming a
CPU, allocation, memory, latency, or throughput improvement.
- Read
references/low-level-and-accelerated.md only for a measured hot path
that may justify InlineArray, Span, unsafe buffers, SIMD, or Accelerate.
- Read
references/ranked-sources.md for a source-research request or when a
recommendation is disputed, version-sensitive, or compiler-dependent.
Repository instructions, supported toolchains, deployment targets, and explicit
user scope override generic examples. They never weaken correctness, memory
safety, or evidence gates.
Route the request
- Lead with
$app-performance when the starting point is a whole-app symptom,
field regression, launch, hang, hitch, memory pressure, energy, storage,
networking, graphics, or app size. Apply this skill after evidence identifies
a Swift hot path.
- Lead with
$swiftui-optimization for SwiftUI dependencies, Observation,
identity, view updates, lists, layout, or animation.
- Lead with
$swift-concurrency for isolation, task lifetime, cancellation,
data-race safety, or a staged Swift 6 migration. Use this skill only for a
distinct source-performance question.
- Keep this skill in the lead when the user names a concrete Swift construct,
algorithm, data pipeline, source area, or focused benchmark.
Classify the work
Choose one mode and respect its authority:
- Research: rank useful sources and synthesize supported guidance; do not edit
project code.
- Explain: describe the cost model, uncertainty, and conditions under which a
difference can matter.
- Review: inspect source and report prioritized findings; do not implement
fixes unless requested.
- Improve: make the smallest justified source change and validate it.
- Benchmark: build or refine a focused harness and report its bounded result.
Do not turn a narrow question into a project-wide optimization campaign.
Treat a request to optimize, improve, fix, refactor, or implement as Improve
authority within its named scope. Do not downgrade it to Review because a
profiler, device, or benchmark is unavailable.
Establish the context
- Read repository instructions and inspect version-control status.
- Record the Xcode and Swift toolchain, optimization configuration, deployment
targets, module boundaries, and supported devices.
- Identify the exact operation, input distribution and size, call frequency,
lifetime, concurrency context, and correctness invariants.
- For a known symptom, preserve its scenario and existing trace evidence. For a
preventive review, identify why the code is plausibly hot at production scale.
- Define the metric or evidence needed before changing public APIs, ownership,
data representation, synchronization, or safety.
Treat Debug behavior and unoptimized SIL as diagnostic context, not production
performance evidence.
Inspect costs in order
- Remove unused work, repeated passes, redundant decoding, and avoidable I/O.
- Choose an algorithm and data structure with suitable complexity and locality.
- Reduce repeated materialization, allocation, bridging, and oversized
lifetimes.
- Inspect value copies, copy-on-write uniqueness, ARC traffic, and captures.
- Reduce overly fine tasks, actor hops, synchronization, and executor handoffs.
- Examine dynamic dispatch or specialization only when it remains material.
- Escalate to fixed-size storage, unsafe access, SIMD, or Accelerate last.
In Improve mode, implement a finding by default when source inspection proves
the cost mechanism and the correction is private, low-risk, and
semantics-preserving. Do not require a profiler, chart, Simulator, physical
device, or benchmark first. Keep a finding recommendation-only when edit
authority is absent or API, safety, concurrency, compiler behavior, or a
material tradeoff remains unresolved; state that blocker instead of silently
omitting the finding.
For every finding, report the source location, triggering workload, cost
mechanism, expected scale, safe correction, validation method, and tradeoffs.
Separate impact from confidence; do not manufacture precision from syntax alone.
Apply Swift-specific decisions
- Distinguish stored
static let, stored static var, and computed
static var. Stored type properties initialize lazily once; let expresses
immutability, not a guaranteed smaller or faster representation. A computed
getter may repeat work, while either stored form may retain its value for the
process lifetime. Isolate mutable shared state correctly.
- Choose
struct, enum, or class for semantics and lifetime first. A value
can contain heap storage and copy expensively; a reference can create ARC and
locality costs. Inspect the complete representation.
- Preserve copy-on-write uniqueness where mutation is intended. Do not keep a
tiny
ArraySlice or Substring alive when retaining the full backing storage
is materially worse than copying the needed result.
- Use
reserveCapacity when a useful final-size estimate is known. Do not call
it before every small growth step or assume that preserving capacity always
wins under memory pressure.
- Select
Deque, Set, Dictionary, or another collection from the operations
required. Do not replace Array by fashion.
- Use lazy algorithms when they avoid work or intermediate storage. Full
consumption, retained bases, and type-erasure boundaries can erase the gain.
- Treat
weak and unowned as ownership and safety choices, not generic
performance switches.
- Batch useful concurrent work while preserving isolation, cancellation,
ordering, priority, and error behavior.
Guard against folklore
- Do not claim that
static let is inherently faster than static var, structs
are always faster than classes, generics always beat existentials, or
ContiguousArray, lazy, final, actors, and caching are universal fixes.
- Do not infer heap allocation, copying, specialization, or dispatch solely from
surface syntax; optimizer and module context matter.
- Do not add
@inline(__always), underscored attributes, unchecked access,
unmanaged references, or unsafe pointers without measured need and a safety
argument.
- Do not extrapolate one microbenchmark to launch, scrolling, memory pressure, or
battery impact. Hand those claims to
$app-performance.
- Do not trade correctness, thread safety, API compatibility, or maintainability
for an unmeasured theoretical win.
Verify and report
For changed code, run repository formatting, static analysis, focused tests, and
a production-configuration build for affected targets.
For a direct source-proven correction, treat those correctness checks as
sufficient implementation validation. Report the supported cost, complexity, or
lifetime mechanism and state that performance verification was not run when no
matched benchmark or capture is available.
For a performance claim, compare baseline and candidate with the same optimized
build, workload, environment, and metric. Prefer a representative older physical
device when the claim concerns iOS behavior. Report all valid runs or their
distribution, relevant allocation or memory effects, and secondary regressions.
For source research, rank the most useful sources from 0 to 100 using
authority, applicability, explanatory depth, currency, and actionability. Group
by topic, explain version-sensitive caveats, and prefer primary sources.
Finish with the selected mode, scope, supported mechanism, changed files if any,
checks run, before-and-after evidence if collected, tradeoffs, and remaining
uncertainty. Label an unmeasured recommendation as a hypothesis only when its
mechanism is conditional. Label a source-proven correction as implemented with
performance verification pending, never as a verified improvement.
1---2name: swift-ios-performance3description: Use when researching, writing, reviewing, refactoring, or benchmarking performance-sensitive Swift source in an iOS or iPadOS app, especially algorithms and data structures, allocations and ARC, value copying and copy-on-write, stored or computed static properties, closures, dispatch and specialization, generics and existentials, String or Data processing, Swift concurrency overhead, or safe low-level APIs. Trigger for questions about the runtime or memory cost of a concrete Swift construct, source-level performance reviews, reducing allocations or copies in a known hot path, or focused microbenchmarks. Do not use as the lead skill for whole-app profiling, launch, hangs, hitches, memory pressure, energy, storage, network, graphics, app size, SwiftUI state or updates, or concurrency correctness and Swift 6 migration; use app-performance, swiftui-optimization, or swift-concurrency respectively.4---56# Optimize Swift code for iOS performance78## Outcome910Turn a Swift cost question or known hot path into a semantics-preserving11correction, focused change, or benchmark with an explicit cost mechanism and12evidence proportionate to the decision and claim.1314Prefer the largest reliable gain. Remove unnecessary work before tuning ARC,15dispatch, bounds checks, or generated instructions.1617## Read references selectively1819- Read `references/methodology.md` before researching sources, reviewing a hot20 path, planning a change, or assigning a priority score.21- Read `references/cost-model-and-compiler.md` for allocation, stack versus heap,22 stored versus computed type properties, dispatch, generics, existentials,23 closures, exclusivity, specialization, and build optimization.24- Read `references/ownership-and-memory.md` for struct versus class decisions,25 ARC, weak or unowned references, copy-on-write, slices, captures, bridging, or26 long-lived shared storage.27- Read `references/collections-algorithms-and-text.md` for algorithmic28 complexity, capacity, collection choice, lazy pipelines, `String`, `Substring`,29 `Data`, parsing, mapping, or formatter reuse.30- Read `references/concurrency-costs.md` for task granularity, actor hops,31 executor scheduling, continuations, task groups, or bounded parallelism.32- Read `references/benchmarking.md` before writing a benchmark or claiming a33 CPU, allocation, memory, latency, or throughput improvement.34- Read `references/low-level-and-accelerated.md` only for a measured hot path35 that may justify `InlineArray`, `Span`, unsafe buffers, SIMD, or Accelerate.36- Read `references/ranked-sources.md` for a source-research request or when a37 recommendation is disputed, version-sensitive, or compiler-dependent.3839Repository instructions, supported toolchains, deployment targets, and explicit40user scope override generic examples. They never weaken correctness, memory41safety, or evidence gates.4243## Route the request4445- Lead with `$app-performance` when the starting point is a whole-app symptom,46 field regression, launch, hang, hitch, memory pressure, energy, storage,47 networking, graphics, or app size. Apply this skill after evidence identifies48 a Swift hot path.49- Lead with `$swiftui-optimization` for SwiftUI dependencies, Observation,50 identity, view updates, lists, layout, or animation.51- Lead with `$swift-concurrency` for isolation, task lifetime, cancellation,52 data-race safety, or a staged Swift 6 migration. Use this skill only for a53 distinct source-performance question.54- Keep this skill in the lead when the user names a concrete Swift construct,55 algorithm, data pipeline, source area, or focused benchmark.5657## Classify the work5859Choose one mode and respect its authority:6061- **Research**: rank useful sources and synthesize supported guidance; do not edit62 project code.63- **Explain**: describe the cost model, uncertainty, and conditions under which a64 difference can matter.65- **Review**: inspect source and report prioritized findings; do not implement66 fixes unless requested.67- **Improve**: make the smallest justified source change and validate it.68- **Benchmark**: build or refine a focused harness and report its bounded result.6970Do not turn a narrow question into a project-wide optimization campaign.7172Treat a request to optimize, improve, fix, refactor, or implement as **Improve**73authority within its named scope. Do not downgrade it to Review because a74profiler, device, or benchmark is unavailable.7576## Establish the context77781. Read repository instructions and inspect version-control status.792. Record the Xcode and Swift toolchain, optimization configuration, deployment80 targets, module boundaries, and supported devices.813. Identify the exact operation, input distribution and size, call frequency,82 lifetime, concurrency context, and correctness invariants.834. For a known symptom, preserve its scenario and existing trace evidence. For a84 preventive review, identify why the code is plausibly hot at production scale.855. Define the metric or evidence needed before changing public APIs, ownership,86 data representation, synchronization, or safety.8788Treat Debug behavior and unoptimized SIL as diagnostic context, not production89performance evidence.9091## Inspect costs in order92931. Remove unused work, repeated passes, redundant decoding, and avoidable I/O.942. Choose an algorithm and data structure with suitable complexity and locality.953. Reduce repeated materialization, allocation, bridging, and oversized96 lifetimes.974. Inspect value copies, copy-on-write uniqueness, ARC traffic, and captures.985. Reduce overly fine tasks, actor hops, synchronization, and executor handoffs.996. Examine dynamic dispatch or specialization only when it remains material.1007. Escalate to fixed-size storage, unsafe access, SIMD, or Accelerate last.101102In Improve mode, implement a finding by default when source inspection proves103the cost mechanism and the correction is private, low-risk, and104semantics-preserving. Do not require a profiler, chart, Simulator, physical105device, or benchmark first. Keep a finding recommendation-only when edit106authority is absent or API, safety, concurrency, compiler behavior, or a107material tradeoff remains unresolved; state that blocker instead of silently108omitting the finding.109110For every finding, report the source location, triggering workload, cost111mechanism, expected scale, safe correction, validation method, and tradeoffs.112Separate impact from confidence; do not manufacture precision from syntax alone.113114## Apply Swift-specific decisions115116- Distinguish stored `static let`, stored `static var`, and computed117 `static var`. Stored type properties initialize lazily once; `let` expresses118 immutability, not a guaranteed smaller or faster representation. A computed119 getter may repeat work, while either stored form may retain its value for the120 process lifetime. Isolate mutable shared state correctly.121- Choose `struct`, `enum`, or `class` for semantics and lifetime first. A value122 can contain heap storage and copy expensively; a reference can create ARC and123 locality costs. Inspect the complete representation.124- Preserve copy-on-write uniqueness where mutation is intended. Do not keep a125 tiny `ArraySlice` or `Substring` alive when retaining the full backing storage126 is materially worse than copying the needed result.127- Use `reserveCapacity` when a useful final-size estimate is known. Do not call128 it before every small growth step or assume that preserving capacity always129 wins under memory pressure.130- Select `Deque`, `Set`, `Dictionary`, or another collection from the operations131 required. Do not replace `Array` by fashion.132- Use lazy algorithms when they avoid work or intermediate storage. Full133 consumption, retained bases, and type-erasure boundaries can erase the gain.134- Treat `weak` and `unowned` as ownership and safety choices, not generic135 performance switches.136- Batch useful concurrent work while preserving isolation, cancellation,137 ordering, priority, and error behavior.138139## Guard against folklore140141- Do not claim that `static let` is inherently faster than `static var`, structs142 are always faster than classes, generics always beat existentials, or143 `ContiguousArray`, `lazy`, `final`, actors, and caching are universal fixes.144- Do not infer heap allocation, copying, specialization, or dispatch solely from145 surface syntax; optimizer and module context matter.146- Do not add `@inline(__always)`, underscored attributes, unchecked access,147 unmanaged references, or unsafe pointers without measured need and a safety148 argument.149- Do not extrapolate one microbenchmark to launch, scrolling, memory pressure, or150 battery impact. Hand those claims to `$app-performance`.151- Do not trade correctness, thread safety, API compatibility, or maintainability152 for an unmeasured theoretical win.153154## Verify and report155156For changed code, run repository formatting, static analysis, focused tests, and157a production-configuration build for affected targets.158159For a direct source-proven correction, treat those correctness checks as160sufficient implementation validation. Report the supported cost, complexity, or161lifetime mechanism and state that performance verification was not run when no162matched benchmark or capture is available.163164For a performance claim, compare baseline and candidate with the same optimized165build, workload, environment, and metric. Prefer a representative older physical166device when the claim concerns iOS behavior. Report all valid runs or their167distribution, relevant allocation or memory effects, and secondary regressions.168169For source research, rank the most useful sources from 0 to 100 using170authority, applicability, explanatory depth, currency, and actionability. Group171by topic, explain version-sensitive caveats, and prefer primary sources.172173Finish with the selected mode, scope, supported mechanism, changed files if any,174checks run, before-and-after evidence if collected, tradeoffs, and remaining175uncertainty. Label an unmeasured recommendation as a hypothesis only when its176mechanism is conditional. Label a source-proven correction as implemented with177performance verification pending, never as a verified improvement.