swift - Xcode time profiler accuracy
问题描述
I would like to know the exact time it takes to go from one screen to another. For example how long it takes to login and access the next screen. I tried using the Xcode time profiler but it doesn't log everything. I even enabled the "High frequency" option but still I think that something is missing. What I've come to understand is that you have to use signposts in order to achieve accuracy. Which works but you have to set your iOS version to 12 and also change the code to add os_signpost. Is there another way to achieve this without changing the iOS version? or the code?
Do you have any suggestions of another Xcode profiler tool or another tool in general that can give me this output?
I thought that the time profiler would give me the begin and end time of each method something similar to the Android Studio profiler. Am I missing something?
解决方案
A couple of observations:
Yes, if you want to calculate the time elapsed between two points of code, signposts are a great way of doing that. And if you want to know what’s going on between those two signposts, a “points of interest” range, which you can zoom into by control-clicking. This lets you focus on the area in question:
I'd suggest selecting “Record Waiting Threads”. Sometimes your thread is blocked by something, and if you don’t choose this option, it won't capture samples when your thread is blocked, often making it harder to find the culprit.
(I also tend to record in deferred mode, too, to minimize the observer effect.)
You said
you have to set your iOS version to 12 ...
Well, not quite. Sure, if you want to use
os_signpost
you have to do your profiling on an iOS 12 device/simulator, but you don’t have have to change the target of your app. You'd only have to wrap your logging statements in#available
blocks, e.g.:import UIKit import os.log @available(iOS 12.0, *) let pointsOfInterest = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: .pointsOfInterest) class ViewController: UIViewController { @IBAction func didTapNextButton(_ sender: Any) { if #available(iOS 12.0, *) { os_signpost(.begin, log: pointsOfInterest, name: "Transition") } performSegue(withIdentifier: "Next", sender: self) } }
and
import UIKit import os.log class SecondViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() somethingSlow() } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) if #available(iOS 12.0, *) { os_signpost(.end, log: pointsOfInterest, name: "Transition") } } func somethingSlow() { ... } }
If you don't like having that
if #available
check and you have to support older OS versions, just usekdebug
:kdebug_signpost_start(0, 0, 0, 0, 0)
and
kdebug_signpost_end(0, 0, 0, 0, 0)
You don't have nice names on your points of interest ranges, but it works in older iOS versions.
For more information, see WWDC 2018 video Measuring Performance Using Logging.
推荐阅读
- zapier - 尝试使用 Integromat 进行 Podio API 调用,返回 403 禁止 - InvalidAccessTokenError
- spring-webflux - 在生产者 Spring Reactive Kafka 中使用多个主题配置
- asp.net - 在特定实体上使用身份框架
- android - 创建启动系统应用程序“文件”的意图
- android - 家长控制应用程序如何查看社交媒体消息(例如 Messenger)
- laravel - 如何使用livewire alpinejs Tom select动态添加多选?
- weblogic - 无法在 Weblogic 服务器上启动已停止的应用程序
- r - 在 R 中创建矩阵,有没有更快的方法?
- angular - 为使用 jasmine karma 以数组形式返回 promise 的方法编写单元测试用例
- java - 为什么约束集不起作用我也链接了它们?