Optimising Hot Paths: COW, Inlining and Specialisation
Applying @inline, @_specialize and value-type optimisations based on profiler data.
Optimising Hot Paths: COW, Inlining and Specialisation is a free Swift Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Identify Before Optimising
Always profile first. Optimise only code that the Time Profiler identifies as a hot path — premature optimisation wastes time.
// Measure → Identify → Optimise → Re-measure
// A 10ms function called once is less important than
// a 0.1ms function called 10,000 times per frameCopy-on-Write (COW)
Swift value types (Array, Dictionary) use COW: storage is shared until a mutation occurs, avoiding unnecessary copies.
var a = [1, 2, 3, 4, 5]
var b = a // no copy yet, shared buffer
b.append(6) // copy happens here (b mutates)
print(a.count) // 5 — a unchangedEnsuring COW in Custom Types
Implement COW in custom value types by wrapping mutable state in a reference type and copying before mutation.
struct Matrix {
private class Storage { var data: [[Double]] }
private var storage = Storage()
private mutating func ensureUnique() {
if !isKnownUniquelyReferenced(&storage) {
storage = Storage(data: storage.data) // copy on write
}
}
mutating func set(row: Int, col: Int, value: Double) {
ensureUnique()
storage.data[row][col] = value
}
}@inline(__always)
Force the compiler to inline a function at every call site, eliminating call overhead for tiny functions called in tight loops.
@inline(__always)
func clamp(_ value: Float, _ min: Float, _ max: Float) -> Float {
return Swift.max(min, Swift.min(max, value))
}@inline(never)
Prevent inlining to reduce code size or force the compiler to treat a path as cold (rare).
@inline(never)
func handleUnexpectedError(_ error: Error) {
// Large error-handling block — never inline to keep hot path small
}@_specialize for Generics
Instruct the compiler to emit a specialized copy of a generic function for a specific type, enabling static dispatch and SIMD optimisations.
@_specialize(where T == Float)
@_specialize(where T == Double)
func normalize<T: FloatingPoint>(_ values: [T]) -> [T] {
let max = values.max()!
return values.map { $0 / max }
}Whole-Module Optimization
WMO (enabled in Release) allows the compiler to inline and specialise across file boundaries within a module.
// Xcode: Build Settings → Swift Compiler → Code Generation
// Optimization Level: Optimize for Speed (-O)
// Compilation Mode: Whole Module
// Enables cross-file inlining and dead code eliminationAvoiding ARC Overhead
Frequent reference type creation in hot paths causes ARC retain/release overhead. Prefer value types or cache references.
// HOT PATH:
for _ in 0..<1_000_000 {
let obj = HeavyClass() // alloc + dealloc + ARC overhead
}
// BETTER: allocate once outside the loop
let obj = HeavyClass()
for _ in 0..<1_000_000 { obj.process() }Using ContiguousArray
ContiguousArray guarantees contiguous storage (unlike Array for class elements), improving cache performance in tight loops.
var nums = ContiguousArray<Float>(repeating: 0, count: 10_000)
// Faster iteration than Array<Float> for bridged-to-ObjC typesReducing Protocol Witness Table Lookups
Protocol dynamic dispatch uses witness tables. Generics + specialization replaces witness table lookups with direct calls.
// Dynamic dispatch (slower for hot path):
func process(_ drawable: any Drawable) { drawable.draw() }
// Static dispatch after specialization:
func process<T: Drawable>(_ drawable: T) { drawable.draw() }
// Compiler may devirtualize and inlineBenchmark with XCTMeasure
Always validate optimisations with XCTMeasure benchmarks in your test suite to prevent regressions.
func testNormalizePerformance() {
let data = Array(0..<100_000).map { Float($0) }
measure {
_ = normalize(data)
}
}Quick Check
What does isKnownUniquelyReferenced(_:) check when implementing Copy-on-Write?
Lesson Recap
Profile first with Instruments. Rely on Swift's built-in COW for collections; implement it in custom value types with isKnownUniquelyReferenced. Use @inline(__always) for tiny hot-path functions, @_specialize for generic hotspots, and enable WMO in Release builds. Validate every optimization with XCTMeasure benchmarks.
Frequently asked questions
Is the “Optimising Hot Paths: COW, Inlining and Specialisation” lesson free?
Yes — the full text of “Optimising Hot Paths: COW, Inlining and Specialisation” is free to read here on the web, and the Swift Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Swift Academy course, upgrade to CoddyKit PRO.
What will I learn in “Optimising Hot Paths: COW, Inlining and Specialisation”?
Applying @inline, @_specialize and value-type optimisations based on profiler data. You practise Swift Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Swift Academy?
No prior experience is required. Swift Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Optimising Hot Paths: COW, Inlining and Specialisation” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Swift Academy lesson?
Yes. Every Swift Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Instruments Basics: Time Profiler
- Allocations and Leaks Instruments
- Main Thread Checker and Hangs
- Optimising Hot Paths: COW, Inlining and Specialisation