commit 9710be2af08ea4fe161a4d71be872922e118b76c
parent cdabb255639aa9fe539cfedef586273318354820
Author: Michael Camilleri <[email protected]>
Date: Wed, 22 Apr 2026 00:21:13 +0900
Add further performance logging
Diffstat:
2 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/ListlessiOS/Helpers/PerfSampler.swift b/ListlessiOS/Helpers/PerfSampler.swift
@@ -36,6 +36,14 @@ final class PerfSampler {
private var callCounts: [String: Int] = [:]
private let launchClockStart: DispatchTime
private var dirty = false
+ private var pendingKeyboardWillShow: DispatchTime?
+
+ /// Anchors the launch clock as early as possible. Call once from
+ /// `ListlessiOSApp.init()`; otherwise the clock starts whenever the
+ /// singleton is first accessed (usually the first `makeUIView`).
+ static func markLaunchStart() {
+ _ = shared
+ }
private init() {
let dir = try? FileManager.default.url(
@@ -68,6 +76,37 @@ final class PerfSampler {
) { _ in
Task { @MainActor in PerfSampler.shared.flush() }
}
+ NotificationCenter.default.addObserver(
+ forName: UIResponder.keyboardWillShowNotification,
+ object: nil,
+ queue: .main
+ ) { _ in
+ Task { @MainActor in PerfSampler.shared.keyboardWillShow() }
+ }
+ NotificationCenter.default.addObserver(
+ forName: UIResponder.keyboardDidShowNotification,
+ object: nil,
+ queue: .main
+ ) { _ in
+ Task { @MainActor in PerfSampler.shared.keyboardDidShow() }
+ }
+ }
+
+ private func keyboardWillShow() {
+ pendingKeyboardWillShow = DispatchTime.now()
+ record(label: "Keyboard.willShow", durationMs: 0)
+ }
+
+ private func keyboardDidShow() {
+ let durationMs: Double
+ if let start = pendingKeyboardWillShow {
+ let ns = DispatchTime.now().uptimeNanoseconds &- start.uptimeNanoseconds
+ durationMs = Double(ns) / 1_000_000
+ } else {
+ durationMs = 0
+ }
+ pendingKeyboardWillShow = nil
+ record(label: "Keyboard.didShow", durationMs: durationMs)
}
@discardableResult
diff --git a/ListlessiOS/ListlessiOSApp.swift b/ListlessiOS/ListlessiOSApp.swift
@@ -118,6 +118,7 @@ struct ListlessiOSApp: App {
private let keyValueSyncBridge = KeyValueSyncBridge(keys: ["listName", "colorTheme"])
init() {
+ PerfSampler.markLaunchStart()
let isUITesting = ProcessInfo.processInfo.arguments.contains("UI_TESTING")
persistenceController = isUITesting ? PersistenceController(inMemory: true) : .shared
keyValueSyncBridge.start()