Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2025 Swift

WWDC25 · 32 min · Swift

Improve memory usage and performance with Swift

Discover ways to improve the performance and memory management of your Swift code. We’ll explore ways to refine your code – from making high-level algorithmic changes to adopting the new InlineArray and Span types for finer control over memory and allocations.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 15 snippets

Corrected Data.readByte() method swift · at 7:01 ↗
import Foundation

extension Data {
  /// Consume a single byte from the start of this data.
  mutating func readByte() -> UInt8? {
    guard !isEmpty else { return nil }
    return self.popFirst()
  }
}
RGBAPixel.data(channels:) method swift · at 9:56 ↗
extension RGBAPixel {
  /// Returns the RGB or RGBA values for this pixel, as specified
  /// by the given channels information.
  func data(channels: QOI.Channels) -> some Collection<UInt8> {
    switch channels {
    case .rgb:
      [r, g, b]
    case .rgba:
      [r, g, b, a]
    }
  }
}
Original QOIParser.parseQOI(from:) method swift · at 10:21 ↗
extension QOIParser {
  /// Parses an image from the given QOI data.
  func parseQOI(from input: inout Data) -> QOI? {
    guard let header = QOI.Header(parsing: &input) else { return nil }
    
    let pixels = readEncodedPixels(from: &input)
      .flatMap { decodePixels(from: $0) }
      .prefix(header.pixelCount)
      .flatMap { $0.data(channels: header.channels) }

    return QOI(header: header, data: Data(pixels))
  }
}
Revised QOIParser.parseQOI(from:) method swift · at 12:53 ↗
extension QOIParser {
  /// Parses an image from the given QOI data.
  func parseQOI(from input: inout Data) -> QOI? {
    guard let header = QOI.Header(parsing: &input) else { return nil }
    
    let totalBytes = header.pixelCount * Int(header.channels.rawValue)
    var pixelData = Data(repeating: 0, count: totalBytes)
    var offset = 0
    
    while offset < totalBytes {
      guard let nextPixel = parsePixel(from: &input) else { break }
      
      switch nextPixel {
      case .run(let count):
        for _ in 0..<count {
          state.previousPixel
            .write(to: &pixelData, at: &offset, channels: header.channels)
        }
      default:
        decodeSinglePixel(from: nextPixel)
          .write(to: &pixelData, at: &offset, channels: header.channels)
      }
    }
    
    return QOI(header: header, data: pixelData)
  }
}
Array behavior swift · at 15:07 ↗
var array = [1, 2, 3]
array.append(4)
array.removeFirst()
// array == [2, 3, 4]

var copy = array
copy[0] = 10      // copy happens on mutation
// array == [2, 3, 4]
// copy == [10, 3, 4]
InlineArray behavior (part 1) swift · at 19:47 ↗
var array: InlineArray<3, Int> = [1, 2, 3]
array[0] = 4
// array == [4, 2, 3]

// Can't append or remove elements
array.append(4)
// error: Value of type 'InlineArray<3, Int>' has no member 'append'

// Can only assign to a same-sized inline array
let bigger: InlineArray<6, Int> = array
// error: Cannot assign value of type 'InlineArray<3, Int>' to type 'InlineArray<6, Int>'
InlineArray behavior (part 2) swift · at 20:23 ↗
var array: InlineArray<3, Int> = [1, 2, 3]
array[0] = 4
// array == [4, 2, 3]

var copy = array    // copy happens on assignment
for i in copy.indices {
    copy[i] += 10
}
// array == [4, 2, 3]
// copy == [14, 12, 13]
processUsingBuffer() function swift · at 23:13 ↗
// Safe usage of a buffer pointer
func processUsingBuffer(_ array: [Int]) -> Int {
    array.withUnsafeBufferPointer { buffer in
        var result = 0
        for i in 0..<buffer.count {
            result += calculate(using: buffer, at: i)
        }
        return result
    }
}
Dangerous getPointerToBytes() function swift · at 23:34 ↗
// Dangerous - DO NOT USE!
func getPointerToBytes() -> UnsafePointer<UInt8> {
    let array: [UInt8] = Array(repeating: 0, count: 128)
    // DANGER: The next line escapes a pointer
    let pointer = array.withUnsafeBufferPointer { $0.baseAddress! }
    // DANGER: The next line returns the escaped pointer
    return pointer
}
processUsingSpan() function swift · at 24:46 ↗
// Safe usage of a span
@available(macOS 16.0, *)
func processUsingSpan(_ array: [Int]) -> Int {
    let intSpan = array.span
    var result = 0
    for i in 0..<intSpan.count {
        result += calculate(using: intSpan, at: i)
    }
    return result
}
getHiddenSpanOfBytes() function (attempt 1) swift · at 25:07 ↗
@available(macOS 16.0, *)
func getHiddenSpanOfBytes() -> Span<UInt8> { }
// error: Cannot infer lifetime dependence...
getHiddenSpanOfBytes() function (attempt 2) swift · at 25:28 ↗
@available(macOS 16.0, *)
func getHiddenSpanOfBytes() -> () -> Int {
    let array: [UInt8] = Array(repeating: 0, count: 128)
    let span = array.span
    return { span.count }
}
RawSpan.readByte() method swift · at 26:27 ↗
@available(macOS 16.0, *)
extension RawSpan {
  mutating func readByte() -> UInt8? {
    guard !isEmpty else { return nil }
    
    let value = unsafeLoadUnaligned(as: UInt8.self)
    self = self._extracting(droppingFirst: 1)
    return value
  }
}
Final QOIParser.parseQOI(from:) method swift · at 28:02 ↗
/// Parses an image from the given QOI data.
mutating func parseQOI(from input: inout RawSpan) -> QOI? {
  guard let header = QOI.Header(parsing: &input) else { return nil }
  
  let totalBytes = header.pixelCount * Int(header.channels.rawValue)
  
  let pixelData = Data(rawCapacity: totalBytes) { outputSpan in
    while outputSpan.count < totalBytes {
      guard let nextPixel = parsePixel(from: &input) else { break }
      
      switch nextPixel {
      case .run(let count):
        for _ in 0..<count {
          previousPixel
            .write(to: &outputSpan, channels: header.channels)
        }
        
      default:
        decodeSinglePixel(from: nextPixel)
          .write(to: &outputSpan, channels: header.channels)
        
      }
    }
  }
  
  return QOI(header: header, data: pixelData)
}
RGBAPixel.write(to:channels:) method swift · at 28:31 ↗
@available(macOS 16.0, *)
extension RGBAPixel {
  /// Writes this pixel's RGB or RGBA data into the given output span.
  @lifetime(&output)
  func write(to output: inout OutputRawSpan, channels: QOI.Channels) {
    output.append(r)
    output.append(g)
    output.append(b)
    
    if channels == .rgba {
      output.append(a)
    }
  }
}

Resources