Section 11/151 menit
11. Performa dan Optimasi
11. Performa dan Optimasi
Profiling AI Performance
swift
import os
// Gunakan os_signpost untuk profiling AI requests
let log = OSLog(subsystem: "com.company.app", category: "AIPerformance")
class ProfiledVisionAnalyzer {
func profiledOCR(image: UIImage) async -> [String] {
let signpostID = OSSignpostID(log: log)
os_signpost(.begin, log: log, name: "OCR Request", signpostID: signpostID,
"Image size: %{public}@", "\(image.size)")
defer {
os_signpost(.end, log: log, name: "OCR Request", signpostID: signpostID)
}
guard let cgImage = image.cgImage else { return [] }
let request = VNRecognizeTextRequest()
try? VNImageRequestHandler(cgImage: cgImage).perform([request])
return request.results?.compactMap { $0.topCandidates(1).first?.string } ?? []
}
}
Batching dan Async Processing
swift
// Proses multiple gambar secara concurrent dengan throttling
class BatchImageAnalyzer {
private let maxConcurrency = 4 // sesuaikan dengan jumlah core
func analyzeImages(_ images: [UIImage]) async -> [AnalysisResult] {
await withTaskGroup(of: AnalysisResult?.self) { group in
// Batasi concurrent task
let semaphore = AsyncSemaphore(limit: maxConcurrency)
for (index, image) in images.enumerated() {
group.addTask {
await semaphore.wait()
defer { semaphore.signal() }
let text = await self.extractText(from: image)
return AnalysisResult(index: index, text: text)
}
}
var results: [AnalysisResult] = []
for await result in group {
if let result { results.append(result) }
}
return results.sorted { $0.index < $1.index }
}
}
private func extractText(from image: UIImage) async -> String {
guard let cgImage = image.cgImage else { return "" }
let request = VNRecognizeTextRequest()
try? VNImageRequestHandler(cgImage: cgImage).perform([request])
return request.results?.compactMap { $0.topCandidates(1).first?.string }.joined(separator: " ") ?? ""
}
}
struct AnalysisResult {
let index: Int
let text: String
}
// Simple AsyncSemaphore implementation
actor AsyncSemaphore {
private var count: Int
private var waiters: [CheckedContinuation<Void, Never>] = []
init(limit: Int) { count = limit }
func wait() async {
if count > 0 { count -= 1; return }
await withCheckedContinuation { waiters.append($0) }
}
func signal() {
if waiters.isEmpty { count += 1 }
else { waiters.removeFirst().resume() }
}
}