Streaming is available in most browsers,
and in the Developer app.
-
Explore Swift performance
Discover how Swift balances abstraction and performance. Learn what elements of performance to consider and how the Swift optimizer affects them. Explore the different features of Swift and how they're implemented to further understand the tradeoffs available that can impact performance.
Chapters
- 0:00 - Introduction
- 1:24 - Agenda
- 1:46 - What is performance?
- 4:31 - Low-level principles
- 4:36 - Function calls
- 8:29 - Memory allocation
- 10:34 - Memory layout
- 13:57 - Value copying
- 20:54 - Putting it together
- 21:08 - Dynamically-sized types
- 24:33 - Async functions
- 28:11 - Closures
- 30:36 - Generics
- 34:00 - Wrap up
Resources
Related Videos
WWDC24
WWDC19
WWDC16
-
DownloadArray
-
-
0:24 - An example C function, with self-evident allocation
int main(int argc, char **argv) { int count = argc - 1; int *arr = malloc(count * sizeof(int)); int i; for (i = 0; i < count; ++i) { arr[i] = atoi(argv[i + 1]); } free(arr); }
-
0:50 - An example Swift function, with a lot of implicit abstraction
func main(args: [String]) { let arr = args.map { Int($0) ?? 0 } }
-
4:39 - An example of a function call
URLSession.shared.data(for: request)
-
6:30 - A Swift function that calls a method on a value of protocol type
func updateAll(models: [any DataModel], from source: DataSource) { for model in models { model.update(from: source) } }
-
6:40 - A declaration of the method where it's a protocol requirement using dynamic dispatch
protocol DataModel { func update(from source: DataSource) }
-
6:50 - A declaration of the method where it's a protocol extension method using static dispatch
protocol DataModel { func update(from source: DataSource, quickly: Bool) } extension DataModel { func update(from source: DataSource) { self.update(from: source, quickly: true) } }
-
7:00 - The same function as before, which we're now talking about the local state within
func updateAll(models: [any DataModel], from source: DataSource) { for model in models { model.update(from: source) } }
-
7:18 - Partial assembly code for that function, showing instructions to adjust the stack pointer
_$s4main9updateAll6models4fromySayAA9DataModel_pG_AA0F6SourceCtF: sub sp, sp, #208 stp x29, x30, [sp, #192] … ldp x29, x30, [sp, #192] add sp, sp, #208 ret
-
7:59 - A C struct showing one possible layout of the function's call frame
// sizeof(CallFrame) == 208 struct CallFrame { Array<AnyDataModel> models; DataSource source; AnyDataModel model; ArrayIterator iterator; ... void *savedX29; void *savedX30; };
-
10:50 - A line of code containing a single variable initialization
var array = [ 1.0, 2.0 ]
-
11:44 - Using the MemoryLayout type to examine a type's inline representation
MemoryLayout.size(ofValue: array) == 8
-
12:48 - The variable initialization from before, now placed within a function
func makeArray() { var array = [ 1.0, 2.0 ] }
-
15:42 - Initializing a second variable with the contents of the first
func makeArray() { var array = [ 1.0, 2.0 ] var array2 = array }
-
16:27 - Taking the value of an existing variable with the consume operator
func makeArray() { var array = [ 1.0, 2.0 ] var array2 = consume array }
-
16:58 - A call to a mutating method
func makeArray() { var array = [ 1.0, 2.0 ] array.append(3.0) }
-
17:40 - Passing an argument that should be borrowable
func makeArray() { var array = [ 1.0, 2.0 ] print(array) }
-
18:10 - Passing an argument that will likely have to be defensively copied
func makeArray(object: MyClass) { object.array = [ 1.0, 2.0 ] print(object.array) }
-
19:27 - Part of a large struct type
struct Person { var name: String var birthday: Date var address: String var relationships: [Relationship] ... }
-
21:22 - A Connection struct that contains a property of the dynamically-sized URL type
struct Connection { var username: String var address: URL var options: [String: String] }
-
21:40 - A GenericConnection struct that contains a property of an unknown type parameter type
struct GenericConnection<T> { var username: String var address: T var options: [String: String] }
-
21:51 - The same GenericConnection struct, except with a class constraint on the type parameter
struct GenericConnection<T> where T: AnyObject { var username: String var address: T var options: [String: String] }
-
22:27 - The same Connection struct as before
struct Connection { var username: String var address: URL var options: [String: String] }
-
23:23 - A global variable of URL type
var address = URL(string: "...")
-
23:42 - A local variable of URL type
func workWithAddress() { var address = URL(string: "...") }
-
25:02 - An async function
func awaitAll(tasks: [Task<Int, Never>]) async -> [Int] { var results = [Int]() for task in tasks { results.append(await task.value) } return results }
-
28:21 - A function that takes an argument of function type
func sumTwice(f: () -> Int) -> Int { return f() + f() }
-
28:30 - A C function roughly corresponding to the Swift function
Int sumTwice(Int (*fFunction)(void *), void *fContext) { return fFunction(fContext) + fFunction(fContext); }
-
28:47 - A function call that passes a closure expression as a function argument
func sumTwice(f: () -> Int) -> Int { return f() + f() } func puzzle(n: Int) -> Int { return sumTwice { n + 1 } }
-
29:15 - C code roughly corresponding to the emission of the non-escaping closure
struct puzzle_context { Int n; }; Int puzzle(Int n) { struct puzzle_context context = { n }; return sumTwice(&puzzle_closure, &context); } Int puzzle_closure(void *_context) { struct puzzle_context *context = (struct puzzle_context *) _context; return _context->n + 1; }
-
29:34 - The function and its caller again, now taking an escaping function as its parameter
func sumTwice(f: @escaping () -> Int) -> Int { return f() + f() } func puzzle(n: Int) -> Int { return sumTwice { n + 1 } }
-
29:53 - A closure that captures a local variable by reference
func sumTwice(f: () -> Int) -> Int { return f() + f() } func puzzle(n: Int) -> Int { var addend = 0 return sumTwice { addend += 1 return n + addend } }
-
30:30 - Swift types roughly approximating how escaping variables and closures are handled
class Box<T> { let value: T } class puzzle_context { let n: Int let addend: Box<Int> }
-
30:40 - A generic function that calls a protocol requirement
protocol DataModel { func update(from source: DataSource) } func updateAll<Model: DataModel>(models: [Model], from source: DataSource) { for model in models { model.update(from: source) } }
-
31:03 - A C struct roughly approximating a protocol witness table
struct DataModelWitnessTable { ConformanceDescriptor *identity; void (*update)(DataSource source, TypeMetadata *Self); };
-
31:20 - A C function signature roughly approximating how generic functions receive generic parameters
void updateAll(Array<Model> models, DataSource source, TypeMetadata *Model, DataModelWitnessTable *Model_is_DataModel);
-
31:36 - A function that receives an array of values of protocol type
protocol DataModel { func update(from source: DataSource) } func updateAll(models: [any DataModel], from source: DataSource)
-
31:49 - A C struct roughly approximating the layout of the Swift type `any DataModel`
struct AnyDataModel { OpaqueValueStorage value; TypeMetadata *valueType; DataModelWitnessTable *value_is_DataModel; }; struct OpaqueValueStorage { void *storage[3]; };
-
31:50 - A contrast of the two Swift function signatures from before
protocol DataModel { func update(from source: DataSource) } func updateAll<Model: DataModel>(models: [Model], from source: DataSource) { for model in models { model.update(from: source) } } func updateAll(models: [any DataModel], from source: DataSource) { for model in models { model.update(from: source) } }
-
32:57 - Specialization of a generic function for known type parameters
func updateAll<Model: DataModel>(models: [Model], from source: DataSource) { for model in models { model.update(from: source) } } var myModels: [MyDataModel] updateAll(models: myModels, from: source) // Implicitly generated by the optimizer func updateAll_specialized(models: [MyDataModel], from source: DataSource) { for model in models { model.update(from: source) } }
-
-
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.