-
Visualize and optimize Swift concurrency
Learn how you can optimize your app with the Swift Concurrency template in Instruments. We'll discuss common performance issues and show you how to use Instruments to find and resolve these problems. Learn how you can keep your UI responsive, maximize parallel performance, and analyze Swift concurrency activity within your app.
To get the most out of this session, we recommend familiarity with Swift concurrency (including tasks and actors).Ressources
Vidéos connexes
WWDC23
WWDC22
- Eliminate data races using Swift Concurrency
- Track down hangs with Xcode and on-device detection
- What's new in Swift
- What's new in UIKit
WWDC21
-
Rechercher dans cette vidéo…
-
-
10:24 - CompressionState class
@MainActor class CompressionState: ObservableObject { @Published var files: [FileStatus] = [] var logs: [String] = [] func update(url: URL, progress: Double) { if let loc = files.firstIndex(where: {$0.url == url}) { files[loc].progress = progress } } func update(url: URL, uncompressedSize: Int) { if let loc = files.firstIndex(where: {$0.url == url}) { files[loc].uncompressedSize = uncompressedSize } } func update(url: URL, compressedSize: Int) { if let loc = files.firstIndex(where: {$0.url == url}) { files[loc].compressedSize = compressedSize } } func compressAllFiles() { for file in files { Task { let compressedData = compressFile(url: file.url) await save(compressedData, to: file.url) } } } func compressFile(url: URL) -> Data { log(update: "Starting for \(url)") let compressedData = CompressionUtils.compressDataInFile(at: url) { uncompressedSize in update(url: url, uncompressedSize: uncompressedSize) } progressNotification: { progress in update(url: url, progress: progress) log(update: "Progress for \(url): \(progress)") } finalNotificaton: { compressedSize in update(url: url, compressedSize: compressedSize) } log(update: "Ending for \(url)") return compressedData } func log(update: String) { logs.append(update) } -
11:49 - CompressionState class using ParallelCompressor actor
actor ParallelCompressor { var logs: [String] = [] unowned let status: CompressionState init(status: CompressionState) { self.status = status } func compressFile(url: URL) -> Data { log(update: "Starting for \(url)") let compressedData = CompressionUtils.compressDataInFile(at: url) { uncompressedSize in Task { @MainActor in status.update(url: url, uncompressedSize: uncompressedSize) } } progressNotification: { progress in Task { @MainActor in status.update(url: url, progress: progress) await log(update: "Progress for \(url): \(progress)") } } finalNotificaton: { compressedSize in Task { @MainActor in status.update(url: url, compressedSize: compressedSize) } } log(update: "Ending for \(url)") return compressedData } func log(update: String) { logs.append(update) } } @MainActor class CompressionState: ObservableObject { @Published var files: [FileStatus] = [] var compressor: ParallelCompressor! init() { self.compressor = ParallelCompressor(status: self) } func update(url: URL, progress: Double) { if let loc = files.firstIndex(where: {$0.url == url}) { files[loc].progress = progress } } func update(url: URL, uncompressedSize: Int) { if let loc = files.firstIndex(where: {$0.url == url}) { files[loc].uncompressedSize = uncompressedSize } } func update(url: URL, compressedSize: Int) { if let loc = files.firstIndex(where: {$0.url == url}) { files[loc].compressedSize = compressedSize } } func compressAllFiles() { for file in files { Task { let compressedData = await compressor.compressFile(url: file.url) await save(compressedData, to: file.url) } } } } -
17:46 - CompressionState class using ParallelCompressor with minimal actor-isolation and detached tasks
actor ParallelCompressor { var logs: [String] = [] unowned let status: CompressionState init(status: CompressionState) { self.status = status } nonisolated func compressFile(url: URL) async -> Data { await log(update: "Starting for \(url)") let compressedData = CompressionUtils.compressDataInFile(at: url) { uncompressedSize in Task { @MainActor in status.update(url: url, uncompressedSize: uncompressedSize) } } progressNotification: { progress in Task { @MainActor in status.update(url: url, progress: progress) await log(update: "Progress for \(url): \(progress)") } } finalNotificaton: { compressedSize in Task { @MainActor in status.update(url: url, compressedSize: compressedSize) } } await log(update: "Ending for \(url)") return compressedData } func log(update: String) { logs.append(update) } } @MainActor class CompressionState: ObservableObject { @Published var files: [FileStatus] = [] var compressor: ParallelCompressor! init() { self.compressor = ParallelCompressor(status: self) } func update(url: URL, progress: Double) { if let loc = files.firstIndex(where: {$0.url == url}) { files[loc].progress = progress } } func update(url: URL, uncompressedSize: Int) { if let loc = files.firstIndex(where: {$0.url == url}) { files[loc].uncompressedSize = uncompressedSize } } func update(url: URL, compressedSize: Int) { if let loc = files.firstIndex(where: {$0.url == url}) { files[loc].compressedSize = compressedSize } } func compressAllFiles() { for file in files { Task.detached { let compressedData = await self.compressor.compressFile(url: file.url) await save(compressedData, to: file.url) } } } }
-