Swift Academy · Lesson

Optimising Hot Paths: COW, Inlining and Specialisation

Applying @inline, @_specialize and value-type optimisations based on profiler data.

Lesson 4 of 413 steps

Optimising Hot Paths: COW, Inlining and Specialisation is a free Swift Academy lesson on CoddyKit. This is lesson 4 of 4. Any 3 lessons of this learning path are free to read in full — after that, CoddyKit PRO unlocks every lesson, plus hands-on practice with a built-in code editor and a 24/7 AI tutor. It is part of the Swift Academy learning path, and your progress syncs across the web and the CoddyKit app. The Swift Academy course includes 4 lessons in total.

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 frame

Copy-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 unchanged

Ensuring 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 elimination

Avoiding 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 types

Reducing 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 inline

Benchmark 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.

Free to start

Learn Swift with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
122
Lessons
409

Frequently Asked Questions

Is the “Optimising Hot Paths: COW, Inlining and Specialisation” lesson free?

Yes — any 3 lessons of the Swift Academy learning path, including “Optimising Hot Paths: COW, Inlining and Specialisation”, are free to read in full here on the web. After that, CoddyKit PRO unlocks every lesson, plus interactive practice with a built-in code editor and a 24/7 AI tutor. The Swift Academy course includes 4 lessons in total.

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, so you can start here or from the beginning and move at your own pace. This is lesson 4 of 4.

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

  1. Instruments Basics: Time Profiler
  2. Allocations and Leaks Instruments
  3. Main Thread Checker and Hangs
  4. Optimising Hot Paths: COW, Inlining and Specialisation
← Back to Swift Academy