iOS client for Grain grain.social
ios photography atproto
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

perf: preheat API connection at launch to warm DNS/TLS

Fires a fire-and-forget GET to /_health from a detached task in
GrainApp.init(), so DNS + TCP + TLS handshake runs in parallel with
the ~580ms UIKit launch window. By the time the real XRPC calls
fire, the connection pool to grain.social is already warm.

Measured impact on cold-network cold launch: ~150-200ms off TFP.
The ConnectionPreheat signpost interval shows how cold the handshake
was (500-650ms observed on cold runs, ~100ms when already warm).

authored by

Hima Aramona and committed by
Chad Miller
5eed67b8 b103cf64

+10 -1
+9
Grain/GrainApp.swift
··· 25 25 appSignposter.endInterval("NukePipelineSetup", state) 26 26 appLogger.debug("[NukePipelineSetup] end") 27 27 } 28 + Task.detached(priority: .userInitiated) { 29 + let spid = appSignposter.makeSignpostID() 30 + let state = appSignposter.beginInterval("ConnectionPreheat", id: spid) 31 + var req = URLRequest(url: AuthManager.serverURL.appendingPathComponent("_health")) 32 + req.httpMethod = "GET" 33 + req.timeoutInterval = 5 34 + _ = try? await URLSession.shared.data(for: req) 35 + appSignposter.endInterval("ConnectionPreheat", state) 36 + } 28 37 appSignposter.emitEvent("GrainAppInitEnd") 29 38 } 30 39
+1 -1
Grain/Views/Feed/FeedView.swift
··· 446 446 } 447 447 } 448 448 .sheet(item: $reportGallery) { gallery in 449 - ReportView(client: client, subjectUri: gallery.uri, subjectCid: gallery.cid ?? "") 449 + ReportView(client: client, subjectUri: gallery.uri, subjectCid: gallery.cid) 450 450 } 451 451 .alert("Delete Gallery?", isPresented: $showDeleteConfirmation) { 452 452 Button("Delete", role: .destructive) {