Tüm Yazılar
KategoriPerformance
Okuma Süresi
19 dk
Yayın Tarihi
...
Kelime Sayısı
1.308kelime

Kahveni hazırla - bu içerikli bir makale!

App launch time'ı %70 azaltın! Pre-main, post-main optimizasyonları, dylib yönetimi ve Instruments ile profiling teknikleri.

iOS App Launch Optimizasyonu: %70 Hızlandırma Rehberi

App launch time, kullanıcı deneyiminin en kritik metriklerinden biridir. Apple'a göre, kullanıcıların %25'i 3 saniyeden uzun süren uygulamaları terk ediyor. Bu rehberde, launch time'ı dramatik şekilde iyileştirmenin yollarını keşfedeceğiz.


İçindekiler


Launch Time Anatomisi

iOS'ta app launch iki ana fazdan oluşur:

Pre-main Phase

Dylib'lerin yüklenmesi, Objective-C runtime setup, +load metodları:

swift
1// ❌ KÖTÜ - +load metodları pre-main'i yavaşlatır
2@objc class LegacyManager: NSObject {
3 override class func load() {
4 // Bu kod main() öncesi çalışır - KAÇININ!
5 setupLogging()
6 configureAnalytics()
7 }
8}
9 
10// ✅ İYİ - Lazy initialization
11@objc class ModernManager: NSObject {
12 static let shared = ModernManager()
13
14 private init() {
15 // İlk erişimde çalışır
16 setupLogging()
17 configureAnalytics()
18 }
19}

Post-main Phase

AppDelegate/SceneDelegate, ilk UI render:

swift
1// ❌ KÖTÜ - Senkron initialization
2@main
3struct MyApp: App {
4 init() {
5 // Ana thread'i bloklayan işlemler
6 FirebaseApp.configure() // ~200ms
7 Crashlytics.configure() // ~100ms
8 Analytics.configure() // ~150ms
9 // Toplam: ~450ms bekleme!
10 }
11
12 var body: some Scene {
13 WindowGroup {
14 ContentView()
15 }
16 }
17}
18 
19// ✅ İYİ - Async initialization
20@main
21struct MyApp: App {
22 @State private var isInitialized = false
23
24 init() {
25 // Sadece kritik setup
26 configureAppearance()
27 }
28
29 var body: some Scene {
30 WindowGroup {
31 if isInitialized {
32 ContentView()
33 } else {
34 SplashView()
35 .task {
36 await initializeServices()
37 isInitialized = true
38 }
39 }
40 }
41 }
42
43 private func initializeServices() async {
44 // Parallel initialization
45 async let firebase = Task { FirebaseApp.configure() }
46 async let crash = Task { Crashlytics.configure() }
47 async let analytics = Task { Analytics.configure() }
48
49 _ = await (firebase, crash, analytics)
50 }
51}

Dylib Optimizasyonu

Framework Sayısını Azaltın

swift
1// Xcode -> Build Settings ->
2// "Dead Code Stripping" = YES
3// "Link-Time Optimization" = YES
4 
5// Package.swift - Sadece gereken modüller
6dependencies: [
7 // ❌ Tüm Firebase
8 // .package(url: "firebase-ios-sdk", from: "10.0.0"),
9
10 // ✅ Sadece gerekli modüller
11 .product(name: "FirebaseAnalytics", package: "firebase-ios-sdk"),
12 .product(name: "FirebaseAuth", package: "firebase-ios-sdk"),
13]

Static vs Dynamic Linking

swift
1// Package.swift
2let package = Package(
3 name: "MyApp",
4 products: [
5 // Static linking - daha hızlı launch
6 .library(name: "Core", type: .static, targets: ["Core"]),
7 ],
8 targets: [
9 .target(name: "Core"),
10 ]
11)

İlk Ekran Optimizasyonu

Skeleton Loading

swift
1struct HomeView: View {
2 @State private var isLoading = true
3 @State private var data: HomeData?
4
5 var body: some View {
6 Group {
7 if isLoading {
8 HomeSkeletonView()
9 } else if let data = data {
10 HomeContentView(data: data)
11 }
12 }
13 .task {
14 // Kritik data'yı önce yükle
15 data = await loadCriticalData()
16 isLoading = false
17
18 // Diğer data'ları background'da
19 Task.detached(priority: .background) {
20 await preloadSecondaryData()
21 }
22 }
23 }
24}
25 
26struct HomeSkeletonView: View {
27 var body: some View {
28 VStack(spacing: 16) {
29 // Header skeleton
30 RoundedRectangle(cornerRadius: 8)
31 .fill(.gray.opacity(0.3))
32 .frame(height: 60)
33 .shimmer()
34
35 // Content skeletons
36 ForEach(0..<5) { _ in
37 RoundedRectangle(cornerRadius: 12)
38 .fill(.gray.opacity(0.3))
39 .frame(height: 100)
40 .shimmer()
41 }
42 }
43 .padding()
44 }
45}
46 
47// Shimmer effect
48struct ShimmerModifier: ViewModifier {
49 @State private var phase: CGFloat = 0
50
51 func body(content: Content) -> some View {
52 content
53 .overlay(
54 LinearGradient(
55 colors: [.clear, .white.opacity(0.5), .clear],
56 startPoint: .leading,
57 endPoint: .trailing
58 )
59 .offset(x: phase)
60 )
61 .mask(content)
62 .onAppear {
63 withAnimation(.linear(duration: 1.5).repeatForever(autoreverses: false)) {
64 phase = 400
65 }
66 }
67 }
68}

Instruments ile Profiling

App Launch Template

  1. Xcode -> Product -> Profile (⌘I)
  2. "App Launch" template seçin
  3. Record butonuna tıklayın
  4. Uygulama açılışını analiz edin

Önemli Metrikler

Metrik
İyi
Kabul Edilebilir
Kötü
Cold launch
<1s
1-2s
>2s
Warm launch
<0.5s
0.5-1s
>1s
Hot launch
<0.2s
0.2-0.5s
>0.5s

MetricKit ile Monitoring

swift
1import MetricKit
2 
3class LaunchMetricsManager: NSObject, MXMetricManagerSubscriber {
4 static let shared = LaunchMetricsManager()
5
6 func startCollecting() {
7 MXMetricManager.shared.add(self)
8 }
9
10 func didReceive(_ payloads: [MXMetricPayload]) {
11 for payload in payloads {
12 if let launchMetrics = payload.applicationLaunchMetrics {
13 let histogram = launchMetrics.histogrammedTimeToFirstDraw
14
15 // Analytics'e gönder
16 Analytics.log(
17 event: "launch_time",
18 params: [
19 "p50": histogram.bucketEnumerator.allObjects[50],
20 "p95": histogram.bucketEnumerator.allObjects[95],
21 "p99": histogram.bucketEnumerator.allObjects[99]
22 ]
23 )
24 }
25 }
26 }
27}

Checklist

  • +load metodlarını kaldırın
  • Lazy initialization kullanın
  • Framework sayısını minimize edin
  • Static linking tercih edin
  • İlk ekranı optimize edin (skeleton)
  • Async service initialization
  • MetricKit ile monitoring
  • Cold/warm/hot launch testleri

Launch Time Regression Tespiti

Production'da launch time regresyonlarini tespit etmek, optimizasyon kadar onemlidir. CI/CD pipeline'iniza entegre edebileceginiz bir monitoring sistemi kurmaniz gerekir.

os_signpost ile Custom Olcum

swift
1import os.signpost
2 
3// Launch time olcum icin dedicated log
4private let launchLog = OSLog(subsystem: "com.myapp", category: "Launch")
5 
6@main
7struct MyApp: App {
8 init() {
9 // Launch baslangicindan itibaren olcumu baslat
10 os_signpost(.begin, log: launchLog, name: "AppLaunch")
11 }
12 
13 var body: some Scene {
14 WindowGroup {
15 ContentView()
16 .onAppear {
17 // Ilk frame renderlandiginda olcumu bitir
18 os_signpost(.end, log: launchLog, name: "AppLaunch")
19 reportLaunchTime()
20 }
21 }
22 }
23 
24 private func reportLaunchTime() {
25 let launchTime = CFAbsoluteTimeGetCurrent() - processStartTime
26 
27 // Backend'e gonder
28 Analytics.shared.track(.launchTime(
29 duration: launchTime,
30 type: isWarmLaunch ? .warm : .cold,
31 device: UIDevice.current.model,
32 osVersion: UIDevice.current.systemVersion
33 ))
34 }
35}

XCTest ile Otomatik Launch Time Testi

swift
1import XCTest
2 
3final class LaunchPerformanceTests: XCTestCase {
4 func testColdLaunchTime() throws {
5 // Cold launch performance testi
6 measure(metrics: [XCTApplicationLaunchMetric()]) {
7 XCUIApplication().launch()
8 }
9 }
10 
11 func testColdLaunchUnder2Seconds() throws {
12 let app = XCUIApplication()
13 let startTime = CFAbsoluteTimeGetCurrent()
14 app.launch()
15 let elapsed = CFAbsoluteTimeGetCurrent() - startTime
16 
17 XCTAssertLessThan(elapsed, 2.0,
18 "Cold launch 2 saniyenin altinda olmali, simdiki: \(elapsed)s")
19 }
20}

Launch Time Metrikleri Dashboard

Metrik
Hedef
Uyari
Kritik
Cold Launch (p50)
<800ms
800ms-1.5s
>1.5s
Cold Launch (p95)
<1.5s
1.5s-2.5s
>2.5s
Warm Launch (p50)
<400ms
400ms-800ms
>800ms
Pre-main Time
<200ms
200ms-500ms
>500ms
Time to First Frame
<500ms
500ms-1s
>1s
Dylib Loading
<100ms
100ms-300ms
>300ms

Bu metrikleri haftalik olarak izleyerek, herhangi bir regresyonu erken asamada yakalayabilirsiniz. Ozellikle buyuk feature branch'lerin merge'inden sonra launch time testlerini mutlaka calistirin.


Sonuç

App launch optimizasyonu, küçük değişikliklerin büyük etkiler yarattığı bir alandır. Pre-main ve post-main fazlarını anlayarak, lazy initialization kullanarak ve gereksiz framework'leri kaldırarak launch time'ı %70'e kadar iyileştirebilirsiniz.

Easter Egg

Gizli bir bilgi buldun!

Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?

Okuyucu Ödülü

Tebrikler! Bu yazıyı sonuna kadar okuduğun için sana özel bir hediyem var:

ALTIN İPUCU

Bu yazının en değerli bilgisi

Bu ipucu, yazının en önemli çıkarımını içeriyor.

Etiketler

#Performance#Launch Time#iOS#Optimization#App Startup
Muhittin Çamdalı

Muhittin Çamdalı

Senior iOS Developer

12+ yıllık deneyime sahip iOS Developer. Swift, SwiftUI ve modern iOS mimarileri konusunda uzman. Apple platformlarında performanslı ve kullanıcı dostu uygulamalar geliştiriyorum.

iOS Geliştirme Haberleri

Haftalık Swift tips, SwiftUI tricks ve iOS best practices. Spam yok, sadece değerli içerik.

Gizliliğinize saygı duyuyoruz. İstediğiniz zaman abonelikten çıkabilirsiniz.

Paylaş

Bunu da begenebilirsiniz