Section 12/171 menit
12. Profiling dengan Instruments dan Core ML Profiler
12. Profiling dengan Instruments dan Core ML Profiler
Instruments: Core ML Profiler
Xcode 14+ menyertakan template Core ML Profiler di Instruments:
swift
Xcode → Product → Profile (Command+I)
→ Instruments template: Core ML
Instrument ini menampilkan:
- Model loading time: berapa lama
MLModel.load()membutuhkan waktu - Prediction latency: per-prediksi, breakdown per-layer
- Compute unit utilization: berapa % ANE, GPU, CPU
- Memory footprint: peak dan average selama inferensi
Profiling dengan os_signpost
Untuk profiling kustom yang terintegrasi dengan Instruments:
swift
import os
// MARK: - Instrumented Inference
final class InstrumentedModel {
private let model: MLModel
private let log = OSLog(subsystem: "com.yourapp", category: .pointsOfInterest)
private let inferenceSignpost = OSSignpostID(log: OSLog(subsystem: "com.yourapp", category: .pointsOfInterest))
init(model: MLModel) {
self.model = model
}
func predict(input: MLFeatureProvider) throws -> MLFeatureProvider {
let spid = OSSignpostID(log: log)
// Mark mulai inferensi
os_signpost(.begin, log: log, name: "CoreML Inference", signpostID: spid,
"model=%{public}s", "MyModel")
defer {
os_signpost(.end, log: log, name: "CoreML Inference", signpostID: spid)
}
// Mark preprocessing
os_signpost(.event, log: log, name: "Preprocessing", signpostID: spid)
let result = try model.prediction(from: input)
// Mark postprocessing
os_signpost(.event, log: log, name: "Postprocessing", signpostID: spid)
return result
}
}
Latency Benchmarking
swift
// Benchmark tool untuk mengukur latency dan throughput
final class CoreMLBenchmark {
struct BenchmarkResult {
let warmupLatencies: [TimeInterval]
let steadyStateLatencies: [TimeInterval]
let averageLatency: TimeInterval
let p95Latency: TimeInterval
let p99Latency: TimeInterval
let throughputPerSecond: Double
}
func benchmark(
model: MLModel,
sampleInput: MLFeatureProvider,
warmupRuns: Int = 5,
benchmarkRuns: Int = 100
) throws -> BenchmarkResult {
var warmupLatencies: [TimeInterval] = []
var steadyLatencies: [TimeInterval] = []
// Warmup — biarkan JIT dan cache warming terjadi
for _ in 0..<warmupRuns {
let start = CFAbsoluteTimeGetCurrent()
_ = try model.prediction(from: sampleInput)
warmupLatencies.append(CFAbsoluteTimeGetCurrent() - start)
}
// Actual benchmark
for _ in 0..<benchmarkRuns {
let start = CFAbsoluteTimeGetCurrent()
_ = try model.prediction(from: sampleInput)
steadyLatencies.append(CFAbsoluteTimeGetCurrent() - start)
}
let sorted = steadyLatencies.sorted()
let avg = sorted.reduce(0, +) / Double(sorted.count)
let p95 = sorted[Int(Double(sorted.count) * 0.95)]
let p99 = sorted[Int(Double(sorted.count) * 0.99)]
let totalTime = steadyLatencies.reduce(0, +)
let throughput = Double(benchmarkRuns) / totalTime
return BenchmarkResult(
warmupLatencies: warmupLatencies,
steadyStateLatencies: steadyLatencies,
averageLatency: avg,
p95Latency: p95,
p99Latency: p99,
throughputPerSecond: throughput
)
}
func printReport(_ result: BenchmarkResult) {
print("=== Core ML Benchmark Report ===")
print("Average latency: \(String(format: "%.2f", result.averageLatency * 1000))ms")
print("P95 latency: \(String(format: "%.2f", result.p95Latency * 1000))ms")
print("P99 latency: \(String(format: "%.2f", result.p99Latency * 1000))ms")
print("Throughput: \(String(format: "%.1f", result.throughputPerSecond)) predictions/sec")
print("Warmup overhead: \(String(format: "%.2f", result.warmupLatencies.first ?? 0 * 1000))ms")
}
}