Performance Optimization Analysis of Swift Subarray Extraction
This article examines various methods for extracting subarrays in Swift, benchmarking loop‑based copying, range subscripting with map, while loops, and direct memory copying via memcpy, analyzing their execution times, compiler optimizations, and trade‑offs to guide developers toward efficient array handling in performance‑critical applications.
When writing this article, the author successfully optimized a Swift module for a well‑known online quiz platform, achieving a performance boost of dozens of times. The experience is shared, focusing on string parsing, array operations, and pointer manipulation, with a particular emphasis on subarray extraction.
Arrays are a common data structure across many languages, and optimizing them can yield immediate benefits. Extracting a subarray is a frequent operation, and this article compares several implementation strategies to help developers choose the most suitable approach.
Problem Definition
Assume a large array of Int values with 12,000,000 elements. The task is to copy the first 6,000,000 elements into a new array dest.
let arrayCount = 12000000
var array: [Int] = Array(repeating: 0, count: arrayCount)
for i in 0..<array.count {
array[i] = i
}
let destCount = 6000000
var dest: [Int] = []Method 1: Simple for Loop
Allocate dest with the required size and copy each element using a for loop.
print("engine = t1")
let t1 = Date()
// copy
dest = Array(repeating: 0, count: destCount)
for i in 0..<destCount {
dest[i] = array[i]
}
let t2 = Date()
print("time = \(t2.timeIntervalSince(t1))")
print("index of 1024 = \(dest[1024])")Result on the author’s machine: ~1.13 seconds.
Method 2: Range Subscript with map
Swift’s built‑in range subscript returns an ArraySlice. Converting it to an array with map { $0 } yields a copy.
print("engine = t2")
let t1 = Date()
// copy using range and map
dest = array[0..<destCount].map { $0 }
let t2 = Date()
print("time = \(t2.timeIntervalSince(t1))")
print("index of 1024 = \(dest[1024])")Result: ~0.45 seconds, about 2.5 times faster than Method 1.
Method 3: while Loop
Replace the for loop with a while loop.
print("engine = t3")
let t1 = Date()
dest = Array(repeating: 0, count: destCount)
var i = 0
while i < destCount {
dest[i] = array[i]
i += 1
}
let t2 = Date()
print("time = \(t2.timeIntervalSince(t1))")
print("index of 1024 = \(dest[1024])")Result: ~0.18 seconds, roughly 2.44 times faster than Method 2 and 6.12 times faster than Method 1.
Method 4: Direct Memory Copy ( memcpy )
Use the C standard library’s memcpy to copy the raw memory block.
print("engine = t4")
let t1 = Date()
// copy using memcpy
dest = Array(repeating: 0, count: destCount)
memcpy(&dest, &array, destCount * MemoryLayout<Int>.size)
let t2 = Date()
print("time = \(t2.timeIntervalSince(t1))")
print("index of 1024 = \(dest[1024])")Result: ~0.015 seconds, about 12 times faster than Method 3 and 73 times faster than Method 1.
Compiler Optimizations
Enabling Swift’s “Optimize for Speed” flag ( -O) dramatically reduces execution times for all methods. With optimization, Method 4 remains the fastest, but the gap narrows: Method 1 and Method 2 become comparable (~0.015 seconds each), while Method 3 and Method 4 drop to ~0.005 seconds and ~0.0038 seconds respectively.
Method
Without Optimization (s)
With Optimization (s)
t1
1.05
0.015
t2
0.46
0.0159
t3
0.15
0.005
t4
0.009
0.00378
Take‑away Analysis
For most application‑level code, the range‑subscript approach ( array[0..<destCount].map { $0 }) offers a clean, one‑line solution with acceptable performance, especially when compiler optimizations are enabled.
In performance‑critical domains such as audio/video processing, large‑scale image handling, game resource loading, or online judge platforms, the raw memcpy technique can provide decisive speed advantages, albeit with higher implementation risk.
Recommendations
Prefer range subscripting with map for readability and sufficient speed in typical mobile development.
Consider while loops when micro‑optimizing loops, as they can outperform for loops in Swift.
Enable the -O optimization flag for any performance‑sensitive Swift project.
Use memcpy only when the performance gain justifies the added complexity and potential safety concerns.
The full source code referenced in this article is available on GitHub: https://github.com/FengHaiTongLuo/Swift-Study/blob/main/get_subarray_performance_compare.swift .
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
