Skip to content

Commit

Permalink
启动时间检测
Browse files Browse the repository at this point in the history
  • Loading branch information
ming1016 committed Nov 11, 2024
1 parent 5b3042b commit 5d3e534
Show file tree
Hide file tree
Showing 8 changed files with 258 additions and 33 deletions.
31 changes: 31 additions & 0 deletions SwiftPamphletApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,12 @@
3A3168932CE0FD53004DFC5C /* HomeiOSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3168922CE0FD53004DFC5C /* HomeiOSView.swift */; };
3A3168952CE0FFCE004DFC5C /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3A3168942CE0FFCE004DFC5C /* Launch Screen.storyboard */; platformFilter = ios; };
3A46DEF52BD7AAB2008AD993 /* SMDate in Frameworks */ = {isa = PBXBuildFile; productRef = 3A46DEF42BD7AAB2008AD993 /* SMDate */; };
3AA462362CE228CA00774B59 /* NotificationPreheat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA462352CE228CA00774B59 /* NotificationPreheat.swift */; };
3AA462382CE261CC00774B59 /* TaskManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA462372CE261CC00774B59 /* TaskManager.swift */; };
3AA4623D2CE2734E00774B59 /* AsyncAlgorithms in Frameworks */ = {isa = PBXBuildFile; productRef = 3AA4623C2CE2734E00774B59 /* AsyncAlgorithms */; };
3ACA74FB2BD7964A0024B18E /* SMFile in Frameworks */ = {isa = PBXBuildFile; productRef = 3ACA74FA2BD7964A0024B18E /* SMFile */; };
3ADBA84F2CE209FB00B0050B /* MetricManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ADBA84E2CE209FB00B0050B /* MetricManager.swift */; };
3ADBA8512CE216E900B0050B /* Perf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ADBA8502CE216E900B0050B /* Perf.swift */; };
3AE0D59A2BAB0A0600D6D925 /* DeveloperListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE0D5992BAB0A0600D6D925 /* DeveloperListView.swift */; };
3AE0D59E2BAB183100D6D925 /* EditDeveloper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE0D59D2BAB183100D6D925 /* EditDeveloper.swift */; };
3AE4CA382BD7813D005BEF2C /* InfoOrganizer in Frameworks */ = {isa = PBXBuildFile; productRef = 3AE4CA372BD7813D005BEF2C /* InfoOrganizer */; };
Expand Down Expand Up @@ -959,7 +963,10 @@
3A30EFD52CDA818B0029CB2F /* WeatherKit(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "WeatherKit(ap).md"; sourceTree = "<group>"; };
3A3168922CE0FD53004DFC5C /* HomeiOSView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeiOSView.swift; sourceTree = "<group>"; };
3A3168942CE0FFCE004DFC5C /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
3AA462352CE228CA00774B59 /* NotificationPreheat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPreheat.swift; sourceTree = "<group>"; };
3AA462372CE261CC00774B59 /* TaskManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskManager.swift; sourceTree = "<group>"; };
3ADBA84E2CE209FB00B0050B /* MetricManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricManager.swift; sourceTree = "<group>"; };
3ADBA8502CE216E900B0050B /* Perf.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Perf.swift; sourceTree = "<group>"; };
3AE0D5992BAB0A0600D6D925 /* DeveloperListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperListView.swift; sourceTree = "<group>"; };
3AE0D59D2BAB183100D6D925 /* EditDeveloper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditDeveloper.swift; sourceTree = "<group>"; };
3AF2A2DE2BE22A8C00F3BE1B /* UnCategoryInfoListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnCategoryInfoListView.swift; sourceTree = "<group>"; };
Expand All @@ -982,6 +989,7 @@
08F14B402BBDA3EA005B46CC /* NukeUI in Frameworks */,
08F14B422BBDA3EA005B46CC /* NukeVideo in Frameworks */,
08F14B3E2BBDA3EA005B46CC /* NukeExtensions in Frameworks */,
3AA4623D2CE2734E00774B59 /* AsyncAlgorithms in Frameworks */,
3A46DEF52BD7AAB2008AD993 /* SMDate in Frameworks */,
08BF26D32768A5B40064DDAC /* MarkdownUI in Frameworks */,
08397E322B9F39C100DFDD02 /* SwiftSoup in Frameworks */,
Expand Down Expand Up @@ -2268,6 +2276,9 @@
isa = PBXGroup;
children = (
3ADBA84E2CE209FB00B0050B /* MetricManager.swift */,
3ADBA8502CE216E900B0050B /* Perf.swift */,
3AA462352CE228CA00774B59 /* NotificationPreheat.swift */,
3AA462372CE261CC00774B59 /* TaskManager.swift */,
);
path = Performance;
sourceTree = "<group>";
Expand Down Expand Up @@ -2339,6 +2350,7 @@
3A46DEF42BD7AAB2008AD993 /* SMDate */,
0868D00A2BDD37280023C871 /* SMGitHub */,
082036792C02EEA7002FB5E3 /* SMUI */,
3AA4623C2CE2734E00774B59 /* AsyncAlgorithms */,
);
productName = SwiftPamphletApp;
productReference = 086A5F032744E88E00FECE02 /* 戴铭的开发小册子.app */;
Expand Down Expand Up @@ -2381,6 +2393,7 @@
3A46DEF32BD7AAB2008AD993 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMDate" */,
0868D0092BDD37280023C871 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMGitHub" */,
082036782C02EEA7002FB5E3 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMUI" */,
3AA4623B2CE2734E00774B59 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */,
);
productRefGroup = 086A5F042744E88E00FECE02 /* Products */;
projectDirPath = "";
Expand Down Expand Up @@ -2845,6 +2858,7 @@
3AE0D59A2BAB0A0600D6D925 /* DeveloperListView.swift in Sources */,
3A3168932CE0FD53004DFC5C /* HomeiOSView.swift in Sources */,
084417772B99BA3F0049297D /* SidebarView.swift in Sources */,
3AA462362CE228CA00774B59 /* NotificationPreheat.swift in Sources */,
08ED801C2B9D1EEC0069B7EC /* SettingView.swift in Sources */,
0825E4872BC6596F00332378 /* EditCustomSearchView.swift in Sources */,
3AF2A2E92BE239BA00F3BE1B /* ArchivedInfosView.swift in Sources */,
Expand All @@ -2870,10 +2884,12 @@
08A7FF312BEB02EA00E12E5A /* GithubAccessTokenView.swift in Sources */,
086A5F372744ED9600FECE02 /* UserView.swift in Sources */,
086A5F522744EF4C00FECE02 /* ViewComponent.swift in Sources */,
3ADBA8512CE216E900B0050B /* Perf.swift in Sources */,
08CD61FF27758B8A008C0935 /* Token.swift in Sources */,
3AE0D59E2BAB183100D6D925 /* EditDeveloper.swift in Sources */,
08EF35D22BECFDA80098E2D4 /* BookmarkModel.swift in Sources */,
086A5F462744EEB900FECE02 /* FundationFunction.swift in Sources */,
3AA462382CE261CC00774B59 /* TaskManager.swift in Sources */,
084E1A6527B51EDB0072BBB6 /* AutoTask.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -3037,6 +3053,7 @@
);
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 6.6.4;
MERGED_BINARY_TYPE = none;
OTHER_LDFLAGS = (
"-Xlinker",
"-interposable",
Expand Down Expand Up @@ -3090,6 +3107,7 @@
);
MACOSX_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 6.6.4;
MERGED_BINARY_TYPE = none;
PRODUCT_BUNDLE_IDENTIFIER = com.starming.SwiftPamphletAppByMing;
PRODUCT_NAME = "戴铭的开发小册子";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand Down Expand Up @@ -3194,6 +3212,14 @@
minimumVersion = 12.5.0;
};
};
3AA4623B2CE2734E00774B59 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/apple/swift-async-algorithms.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.0.2;
};
};
/* End XCRemoteSwiftPackageReference section */

/* Begin XCSwiftPackageProductDependency section */
Expand Down Expand Up @@ -3253,6 +3279,11 @@
isa = XCSwiftPackageProductDependency;
productName = SMDate;
};
3AA4623C2CE2734E00774B59 /* AsyncAlgorithms */ = {
isa = XCSwiftPackageProductDependency;
package = 3AA4623B2CE2734E00774B59 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */;
productName = AsyncAlgorithms;
};
3ACA74FA2BD7964A0024B18E /* SMFile */ = {
isa = XCSwiftPackageProductDependency;
productName = SMFile;
Expand Down
80 changes: 77 additions & 3 deletions SwiftPamphletApp/App/SwiftPamphletAppApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,33 +11,81 @@ import SwiftData
import InfoOrganizer
import SMFile
import SMGitHub

import os.signpost
import BackgroundTasks

@main
struct SwiftPamphletAppApp: App {
// 启动时间打点
private let launchStartTime = DispatchTime.now()
private let signpostID = OSSignpostID(log: OSLog.default)
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Launch")

#if os(macOS)
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#elseif os(iOS)
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
#endif

init() {
os_signpost(.begin, log: log, name: "Launch", signpostID: signpostID)

let gr = GitHubReq.shared
if SPC.gitHubAccessToken.isEmpty == true {
gr.githubat = SPC.githubAccessToken()
} else {
gr.githubat = SPC.gitHubAccessToken
}
}

@Environment(\.scenePhase) private var phase

var body: some Scene {
WindowGroup {
#if os(macOS)
HomeView()
.modelContainer(for: [IOInfo.self, DeveloperModel.self, BookmarkModel.self], isUndoEnabled: true)
#elseif os(iOS)
HomeiOSView()
.onAppear {
// background fetch
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.starming.fetch", using: nil) { task in
self.handleAppRefresh(task: task as! BGAppRefreshTask)
}
scheduleAppRefresh()

// 任务管理器
// 使用示例


#if DEBUG
// 主界面加载完成,记录终点
let launchEndTime = DispatchTime.now()
let launchTime = Double(launchEndTime.uptimeNanoseconds - launchStartTime.uptimeNanoseconds) / 1_000_000_000
print("手动打点 Post-main : \(launchTime)")

// 查看整体从进程创建到主界面加载完成时间,只在开发环境下执行
if let processStartTime = Perf.getProcessRunningTime() {
print("进程创建到主界面加载完成时间: \(String(format: "%.2f", processStartTime))")
} else {
print("无法获取进程创建时间")
}
#endif

// 记录启动结束
os_signpost(.end, log: log, name: "Launch", signpostID: signpostID)
}
.onChange(of: phase) { oldValue, newValue in
switch newValue {
case .background:
print("background")
default:
break
}
}

// .modelContainer(for: [IOInfo.self, DeveloperModel.self, BookmarkModel.self], isUndoEnabled: true)
#endif

}
#if os(macOS)
.windowToolbarStyle(UnifiedWindowToolbarStyle(showsTitle: true)) // 用来控制是否展示标题
Expand All @@ -49,8 +97,33 @@ struct SwiftPamphletAppApp: App {
#endif

}

#if os(iOS)
// MARK: - Background Task
func scheduleAppRefresh() {
let request = BGAppRefreshTaskRequest(identifier: "com.starming.fetch")
request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 15) // 最早15分钟后运行
do {
try BGTaskScheduler.shared.submit(request)
} catch {
print("后台任务请求失败: \(error)")
}
}
func handleAppRefresh(task: BGAppRefreshTask) {
// 确保任务在有限的时间内完成
task.expirationHandler = {
// 如果任务时间即将耗尽,取消任务
task.setTaskCompleted(success: false)
}

// 模拟数据获取
print("后台任务开始,获取数据")
}
#endif
}



// MARK: - UnCat

#if os(macOS)
Expand All @@ -73,9 +146,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
#elseif os(iOS)
class AppDelegate: NSObject, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
_ = MetricKitManager.shared
_ = MetricKitManager.shared // 上报启动时间
print("didFinishLaunchingWithOptions")
return true
}

}
#endif
30 changes: 0 additions & 30 deletions SwiftPamphletApp/HomeUI/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,6 @@ struct HomeView: View {
selectedDataLinkString = sdLinkStr
_ = WWDCViewModel()

// 性能用,只在开发环境下执行
#if DEBUG
if let processStartTime = getProcessStartTime() {
print("进程创建时间: \(processStartTime)")
} else {
print("无法获取进程创建时间")
}
#endif
})
.onChange(of: selectedDataLinkString, {
sdLinkStr = selectedDataLinkString
Expand All @@ -96,26 +88,4 @@ struct HomeView: View {
}


// 性能用
// 通过 sysctl 获取进程创建时间
func getProcessStartTime() -> Double? {
var kinfo = kinfo_proc()
var size = MemoryLayout<kinfo_proc>.stride
var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]

let result = mib.withUnsafeMutableBufferPointer { mibPtr -> Int32 in
sysctl(mibPtr.baseAddress, 4, &kinfo, &size, nil, 0)
}

guard result == 0 else {
print("sysctl 调用失败,错误码: \(result)")
return nil
}

let startTimeSec = kinfo.kp_proc.p_starttime.tv_sec
let startTimeUsec = kinfo.kp_proc.p_starttime.tv_usec
let startTime = TimeInterval(startTimeSec) + TimeInterval(startTimeUsec) / 1_000_000
let currentTime = Date().timeIntervalSince1970
return currentTime - startTime

}
8 changes: 8 additions & 0 deletions SwiftPamphletApp/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,17 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>com.starming.fetch</string>
</array>
<key>CFBundleLocalizations</key>
<array>
<string>zh</string>
</array>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
</array>
</dict>
</plist>
5 changes: 5 additions & 0 deletions SwiftPamphletApp/Performance/MetricManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,17 @@ import MetricKit
let metricManager = MXMetricManager.shared
metricManager.add(self)
}

deinit {
MXMetricManager.shared.remove(self)
}
}

extension MetricKitManager {
#if os(iOS)
@available(iOS 13.0, *)
func didReceive(_ payloads: [MXMetricPayload]) {
// 获取启动时间数据
guard let firstPayload = payloads.first else { return }
print("Launch Time Data: \(firstPayload.dictionaryRepresentation())")
}
Expand Down
Loading

0 comments on commit 5d3e534

Please sign in to comment.