Skip to content

Commit 5d3e534

Browse files
committed
启动时间检测
1 parent 5b3042b commit 5d3e534

File tree

8 files changed

+258
-33
lines changed

8 files changed

+258
-33
lines changed

SwiftPamphletApp.xcodeproj/project.pbxproj

+31
Original file line numberDiff line numberDiff line change
@@ -480,8 +480,12 @@
480480
3A3168932CE0FD53004DFC5C /* HomeiOSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A3168922CE0FD53004DFC5C /* HomeiOSView.swift */; };
481481
3A3168952CE0FFCE004DFC5C /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 3A3168942CE0FFCE004DFC5C /* Launch Screen.storyboard */; platformFilter = ios; };
482482
3A46DEF52BD7AAB2008AD993 /* SMDate in Frameworks */ = {isa = PBXBuildFile; productRef = 3A46DEF42BD7AAB2008AD993 /* SMDate */; };
483+
3AA462362CE228CA00774B59 /* NotificationPreheat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA462352CE228CA00774B59 /* NotificationPreheat.swift */; };
484+
3AA462382CE261CC00774B59 /* TaskManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA462372CE261CC00774B59 /* TaskManager.swift */; };
485+
3AA4623D2CE2734E00774B59 /* AsyncAlgorithms in Frameworks */ = {isa = PBXBuildFile; productRef = 3AA4623C2CE2734E00774B59 /* AsyncAlgorithms */; };
483486
3ACA74FB2BD7964A0024B18E /* SMFile in Frameworks */ = {isa = PBXBuildFile; productRef = 3ACA74FA2BD7964A0024B18E /* SMFile */; };
484487
3ADBA84F2CE209FB00B0050B /* MetricManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ADBA84E2CE209FB00B0050B /* MetricManager.swift */; };
488+
3ADBA8512CE216E900B0050B /* Perf.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ADBA8502CE216E900B0050B /* Perf.swift */; };
485489
3AE0D59A2BAB0A0600D6D925 /* DeveloperListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE0D5992BAB0A0600D6D925 /* DeveloperListView.swift */; };
486490
3AE0D59E2BAB183100D6D925 /* EditDeveloper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AE0D59D2BAB183100D6D925 /* EditDeveloper.swift */; };
487491
3AE4CA382BD7813D005BEF2C /* InfoOrganizer in Frameworks */ = {isa = PBXBuildFile; productRef = 3AE4CA372BD7813D005BEF2C /* InfoOrganizer */; };
@@ -959,7 +963,10 @@
959963
3A30EFD52CDA818B0029CB2F /* WeatherKit(ap).md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "WeatherKit(ap).md"; sourceTree = "<group>"; };
960964
3A3168922CE0FD53004DFC5C /* HomeiOSView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeiOSView.swift; sourceTree = "<group>"; };
961965
3A3168942CE0FFCE004DFC5C /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = "<group>"; };
966+
3AA462352CE228CA00774B59 /* NotificationPreheat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationPreheat.swift; sourceTree = "<group>"; };
967+
3AA462372CE261CC00774B59 /* TaskManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskManager.swift; sourceTree = "<group>"; };
962968
3ADBA84E2CE209FB00B0050B /* MetricManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MetricManager.swift; sourceTree = "<group>"; };
969+
3ADBA8502CE216E900B0050B /* Perf.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Perf.swift; sourceTree = "<group>"; };
963970
3AE0D5992BAB0A0600D6D925 /* DeveloperListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeveloperListView.swift; sourceTree = "<group>"; };
964971
3AE0D59D2BAB183100D6D925 /* EditDeveloper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditDeveloper.swift; sourceTree = "<group>"; };
965972
3AF2A2DE2BE22A8C00F3BE1B /* UnCategoryInfoListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnCategoryInfoListView.swift; sourceTree = "<group>"; };
@@ -982,6 +989,7 @@
982989
08F14B402BBDA3EA005B46CC /* NukeUI in Frameworks */,
983990
08F14B422BBDA3EA005B46CC /* NukeVideo in Frameworks */,
984991
08F14B3E2BBDA3EA005B46CC /* NukeExtensions in Frameworks */,
992+
3AA4623D2CE2734E00774B59 /* AsyncAlgorithms in Frameworks */,
985993
3A46DEF52BD7AAB2008AD993 /* SMDate in Frameworks */,
986994
08BF26D32768A5B40064DDAC /* MarkdownUI in Frameworks */,
987995
08397E322B9F39C100DFDD02 /* SwiftSoup in Frameworks */,
@@ -2268,6 +2276,9 @@
22682276
isa = PBXGroup;
22692277
children = (
22702278
3ADBA84E2CE209FB00B0050B /* MetricManager.swift */,
2279+
3ADBA8502CE216E900B0050B /* Perf.swift */,
2280+
3AA462352CE228CA00774B59 /* NotificationPreheat.swift */,
2281+
3AA462372CE261CC00774B59 /* TaskManager.swift */,
22712282
);
22722283
path = Performance;
22732284
sourceTree = "<group>";
@@ -2339,6 +2350,7 @@
23392350
3A46DEF42BD7AAB2008AD993 /* SMDate */,
23402351
0868D00A2BDD37280023C871 /* SMGitHub */,
23412352
082036792C02EEA7002FB5E3 /* SMUI */,
2353+
3AA4623C2CE2734E00774B59 /* AsyncAlgorithms */,
23422354
);
23432355
productName = SwiftPamphletApp;
23442356
productReference = 086A5F032744E88E00FECE02 /* 戴铭的开发小册子.app */;
@@ -2381,6 +2393,7 @@
23812393
3A46DEF32BD7AAB2008AD993 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMDate" */,
23822394
0868D0092BDD37280023C871 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMGitHub" */,
23832395
082036782C02EEA7002FB5E3 /* XCLocalSwiftPackageReference "SwiftPamphletApp/SharePackage/SMUI" */,
2396+
3AA4623B2CE2734E00774B59 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */,
23842397
);
23852398
productRefGroup = 086A5F042744E88E00FECE02 /* Products */;
23862399
projectDirPath = "";
@@ -2845,6 +2858,7 @@
28452858
3AE0D59A2BAB0A0600D6D925 /* DeveloperListView.swift in Sources */,
28462859
3A3168932CE0FD53004DFC5C /* HomeiOSView.swift in Sources */,
28472860
084417772B99BA3F0049297D /* SidebarView.swift in Sources */,
2861+
3AA462362CE228CA00774B59 /* NotificationPreheat.swift in Sources */,
28482862
08ED801C2B9D1EEC0069B7EC /* SettingView.swift in Sources */,
28492863
0825E4872BC6596F00332378 /* EditCustomSearchView.swift in Sources */,
28502864
3AF2A2E92BE239BA00F3BE1B /* ArchivedInfosView.swift in Sources */,
@@ -2870,10 +2884,12 @@
28702884
08A7FF312BEB02EA00E12E5A /* GithubAccessTokenView.swift in Sources */,
28712885
086A5F372744ED9600FECE02 /* UserView.swift in Sources */,
28722886
086A5F522744EF4C00FECE02 /* ViewComponent.swift in Sources */,
2887+
3ADBA8512CE216E900B0050B /* Perf.swift in Sources */,
28732888
08CD61FF27758B8A008C0935 /* Token.swift in Sources */,
28742889
3AE0D59E2BAB183100D6D925 /* EditDeveloper.swift in Sources */,
28752890
08EF35D22BECFDA80098E2D4 /* BookmarkModel.swift in Sources */,
28762891
086A5F462744EEB900FECE02 /* FundationFunction.swift in Sources */,
2892+
3AA462382CE261CC00774B59 /* TaskManager.swift in Sources */,
28772893
084E1A6527B51EDB0072BBB6 /* AutoTask.swift in Sources */,
28782894
);
28792895
runOnlyForDeploymentPostprocessing = 0;
@@ -3037,6 +3053,7 @@
30373053
);
30383054
MACOSX_DEPLOYMENT_TARGET = 14.0;
30393055
MARKETING_VERSION = 6.6.4;
3056+
MERGED_BINARY_TYPE = none;
30403057
OTHER_LDFLAGS = (
30413058
"-Xlinker",
30423059
"-interposable",
@@ -3090,6 +3107,7 @@
30903107
);
30913108
MACOSX_DEPLOYMENT_TARGET = 14.0;
30923109
MARKETING_VERSION = 6.6.4;
3110+
MERGED_BINARY_TYPE = none;
30933111
PRODUCT_BUNDLE_IDENTIFIER = com.starming.SwiftPamphletAppByMing;
30943112
PRODUCT_NAME = "戴铭的开发小册子";
30953113
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -3194,6 +3212,14 @@
31943212
minimumVersion = 12.5.0;
31953213
};
31963214
};
3215+
3AA4623B2CE2734E00774B59 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */ = {
3216+
isa = XCRemoteSwiftPackageReference;
3217+
repositoryURL = "https://github.com/apple/swift-async-algorithms.git";
3218+
requirement = {
3219+
kind = upToNextMajorVersion;
3220+
minimumVersion = 1.0.2;
3221+
};
3222+
};
31973223
/* End XCRemoteSwiftPackageReference section */
31983224

31993225
/* Begin XCSwiftPackageProductDependency section */
@@ -3253,6 +3279,11 @@
32533279
isa = XCSwiftPackageProductDependency;
32543280
productName = SMDate;
32553281
};
3282+
3AA4623C2CE2734E00774B59 /* AsyncAlgorithms */ = {
3283+
isa = XCSwiftPackageProductDependency;
3284+
package = 3AA4623B2CE2734E00774B59 /* XCRemoteSwiftPackageReference "swift-async-algorithms" */;
3285+
productName = AsyncAlgorithms;
3286+
};
32563287
3ACA74FA2BD7964A0024B18E /* SMFile */ = {
32573288
isa = XCSwiftPackageProductDependency;
32583289
productName = SMFile;

SwiftPamphletApp/App/SwiftPamphletAppApp.swift

+77-3
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,81 @@ import SwiftData
1111
import InfoOrganizer
1212
import SMFile
1313
import SMGitHub
14-
14+
import os.signpost
15+
import BackgroundTasks
1516

1617
@main
1718
struct SwiftPamphletAppApp: App {
19+
// 启动时间打点
20+
private let launchStartTime = DispatchTime.now()
21+
private let signpostID = OSSignpostID(log: OSLog.default)
22+
private let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "Launch")
23+
1824
#if os(macOS)
1925
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
2026
#elseif os(iOS)
2127
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
2228
#endif
29+
2330
init() {
31+
os_signpost(.begin, log: log, name: "Launch", signpostID: signpostID)
32+
2433
let gr = GitHubReq.shared
2534
if SPC.gitHubAccessToken.isEmpty == true {
2635
gr.githubat = SPC.githubAccessToken()
2736
} else {
2837
gr.githubat = SPC.gitHubAccessToken
2938
}
3039
}
40+
41+
@Environment(\.scenePhase) private var phase
42+
3143
var body: some Scene {
3244
WindowGroup {
3345
#if os(macOS)
3446
HomeView()
3547
.modelContainer(for: [IOInfo.self, DeveloperModel.self, BookmarkModel.self], isUndoEnabled: true)
3648
#elseif os(iOS)
3749
HomeiOSView()
50+
.onAppear {
51+
// background fetch
52+
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.starming.fetch", using: nil) { task in
53+
self.handleAppRefresh(task: task as! BGAppRefreshTask)
54+
}
55+
scheduleAppRefresh()
56+
57+
// 任务管理器
58+
// 使用示例
59+
60+
61+
#if DEBUG
62+
// 主界面加载完成,记录终点
63+
let launchEndTime = DispatchTime.now()
64+
let launchTime = Double(launchEndTime.uptimeNanoseconds - launchStartTime.uptimeNanoseconds) / 1_000_000_000
65+
print("手动打点 Post-main : \(launchTime)")
66+
67+
// 查看整体从进程创建到主界面加载完成时间,只在开发环境下执行
68+
if let processStartTime = Perf.getProcessRunningTime() {
69+
print("进程创建到主界面加载完成时间: \(String(format: "%.2f", processStartTime))")
70+
} else {
71+
print("无法获取进程创建时间")
72+
}
73+
#endif
74+
75+
// 记录启动结束
76+
os_signpost(.end, log: log, name: "Launch", signpostID: signpostID)
77+
}
78+
.onChange(of: phase) { oldValue, newValue in
79+
switch newValue {
80+
case .background:
81+
print("background")
82+
default:
83+
break
84+
}
85+
}
86+
3887
// .modelContainer(for: [IOInfo.self, DeveloperModel.self, BookmarkModel.self], isUndoEnabled: true)
3988
#endif
40-
4189
}
4290
#if os(macOS)
4391
.windowToolbarStyle(UnifiedWindowToolbarStyle(showsTitle: true)) // 用来控制是否展示标题
@@ -49,8 +97,33 @@ struct SwiftPamphletAppApp: App {
4997
#endif
5098

5199
}
100+
101+
#if os(iOS)
102+
// MARK: - Background Task
103+
func scheduleAppRefresh() {
104+
let request = BGAppRefreshTaskRequest(identifier: "com.starming.fetch")
105+
request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 15) // 最早15分钟后运行
106+
do {
107+
try BGTaskScheduler.shared.submit(request)
108+
} catch {
109+
print("后台任务请求失败: \(error)")
110+
}
111+
}
112+
func handleAppRefresh(task: BGAppRefreshTask) {
113+
// 确保任务在有限的时间内完成
114+
task.expirationHandler = {
115+
// 如果任务时间即将耗尽,取消任务
116+
task.setTaskCompleted(success: false)
117+
}
118+
119+
// 模拟数据获取
120+
print("后台任务开始,获取数据")
121+
}
122+
#endif
52123
}
53124

125+
126+
54127
// MARK: - UnCat
55128

56129
#if os(macOS)
@@ -73,9 +146,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
73146
#elseif os(iOS)
74147
class AppDelegate: NSObject, UIApplicationDelegate {
75148
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
76-
_ = MetricKitManager.shared
149+
_ = MetricKitManager.shared // 上报启动时间
77150
print("didFinishLaunchingWithOptions")
78151
return true
79152
}
153+
80154
}
81155
#endif

SwiftPamphletApp/HomeUI/HomeView.swift

-30
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,6 @@ struct HomeView: View {
6666
selectedDataLinkString = sdLinkStr
6767
_ = WWDCViewModel()
6868

69-
// 性能用,只在开发环境下执行
70-
#if DEBUG
71-
if let processStartTime = getProcessStartTime() {
72-
print("进程创建时间: \(processStartTime)")
73-
} else {
74-
print("无法获取进程创建时间")
75-
}
76-
#endif
7769
})
7870
.onChange(of: selectedDataLinkString, {
7971
sdLinkStr = selectedDataLinkString
@@ -96,26 +88,4 @@ struct HomeView: View {
9688
}
9789

9890

99-
// 性能用
100-
// 通过 sysctl 获取进程创建时间
101-
func getProcessStartTime() -> Double? {
102-
var kinfo = kinfo_proc()
103-
var size = MemoryLayout<kinfo_proc>.stride
104-
var mib: [Int32] = [CTL_KERN, KERN_PROC, KERN_PROC_PID, getpid()]
105-
106-
let result = mib.withUnsafeMutableBufferPointer { mibPtr -> Int32 in
107-
sysctl(mibPtr.baseAddress, 4, &kinfo, &size, nil, 0)
108-
}
109-
110-
guard result == 0 else {
111-
print("sysctl 调用失败,错误码: \(result)")
112-
return nil
113-
}
11491

115-
let startTimeSec = kinfo.kp_proc.p_starttime.tv_sec
116-
let startTimeUsec = kinfo.kp_proc.p_starttime.tv_usec
117-
let startTime = TimeInterval(startTimeSec) + TimeInterval(startTimeUsec) / 1_000_000
118-
let currentTime = Date().timeIntervalSince1970
119-
return currentTime - startTime
120-
121-
}

SwiftPamphletApp/Info.plist

+8
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@
22
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
33
<plist version="1.0">
44
<dict>
5+
<key>BGTaskSchedulerPermittedIdentifiers</key>
6+
<array>
7+
<string>com.starming.fetch</string>
8+
</array>
59
<key>CFBundleLocalizations</key>
610
<array>
711
<string>zh</string>
812
</array>
13+
<key>UIBackgroundModes</key>
14+
<array>
15+
<string>fetch</string>
16+
</array>
917
</dict>
1018
</plist>

SwiftPamphletApp/Performance/MetricManager.swift

+5
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,17 @@ import MetricKit
1919
let metricManager = MXMetricManager.shared
2020
metricManager.add(self)
2121
}
22+
23+
deinit {
24+
MXMetricManager.shared.remove(self)
25+
}
2226
}
2327

2428
extension MetricKitManager {
2529
#if os(iOS)
2630
@available(iOS 13.0, *)
2731
func didReceive(_ payloads: [MXMetricPayload]) {
32+
// 获取启动时间数据
2833
guard let firstPayload = payloads.first else { return }
2934
print("Launch Time Data: \(firstPayload.dictionaryRepresentation())")
3035
}

0 commit comments

Comments
 (0)