-
Swift concurrency: Behind the scenes
Dive into the details of Swift concurrency and discover how Swift provides greater safety from data races and thread explosion while simultaneously improving performance. We'll explore how Swift tasks differ from Grand Central Dispatch, how the new cooperative threading model works, and how to ensure the best performance for your apps.
To get the most out of this session, we recommend first watching “Meet async/await in Swift,” “Explore structured concurrency in Swift,” and “Protect mutable state with Swift actors.”Ressources
Vidéos connexes
WWDC23
WWDC22
WWDC21
- Explore structured concurrency in Swift
- Meet async/await in Swift
- Protect mutable state with Swift actors
- Swift concurrency: Update a sample app
- What‘s new in Swift
WWDC17
WWDC16
-
Rechercher dans cette vidéo…
-
-
4:57 - GCD code with hidden performance pitfalls
func deserializeArticles(from data: Data) throws -> [Article] { /* ... */ } func updateDatabase(with articles: [Article], for feed: Feed) { /* ... */ } let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: concurrentQueue) for feed in feedsToUpdate { let dataTask = urlSession.dataTask(with: feed.url) { data, response, error in // ... guard let data = data else { return } do { let articles = try deserializeArticles(from: data) databaseQueue.sync { updateDatabase(with: articles, for: feed) } } catch { /* ... */ } } dataTask.resume() } -
13:18 - Swift concurrency equivalent using a task group
func deserializeArticles(from data: Data) throws -> [Article] { /* ... */ } func updateDatabase(with articles: [Article], for feed: Feed) async { /* ... */ } await withThrowingTaskGroup(of: [Article].self) { group in for feed in feedsToUpdate { group.async { let (data, response) = try await URLSession.shared.data(from: feed.url) // ... let articles = try deserializeArticles(from: data) await updateDatabase(with: articles, for: feed) return articles } } } -
15:16 - Async functions: stack frames and async frames
// on Database func save(_ newArticles: [Article], for feed: Feed) async throws -> [ID] { /* ... */ } // on Feed func add(_ newArticles: [Article]) async throws { let ids = try await database.save(newArticles, for: self) for (id, article) in zip(ids, newArticles) { articles[id] = article } } func updateDatabase(with articles: [Article], for feed: Feed) async throws { // skip old articles ... try await feed.add(articles) } -
37:13 - Excessive context switching due to Main actor hoppping
// on database actor func loadArticle(with id: ID) async throws -> Article { /* ... */ } @MainActor func updateUI(for article: Article) async { /* ... */ } @MainActor func updateArticles(for ids: [ID]) async throws { for id in ids { let article = try await database.loadArticle(with: id) await updateUI(for: article) } } -
38:18 - Batch UI work to reduce the number of context switches
// on database actor func loadArticles(with ids: [ID]) async throws -> [Article] @MainActor func updateUI(for articles: [Article]) async @MainActor func updateArticles(for ids: [ID]) async throws { let articles = try await database.loadArticles(with: ids) await updateUI(for: articles) }
-