是否有一种方法可以确定一个方法需要执行多少时间(以毫秒为单位)?
当前回答
这里有一个Swift 3的解决方案,可以在任何地方对代码进行等分,以找到长时间运行的进程。
var increment: Int = 0
var incrementTime = NSDate()
struct Instrumentation {
var title: String
var point: Int
var elapsedTime: Double
init(_ title: String, _ point: Int, _ elapsedTime: Double) {
self.title = title
self.point = point
self.elapsedTime = elapsedTime
}
}
var elapsedTimes = [Instrumentation]()
func instrument(_ title: String) {
increment += 1
let incrementedTime = -incrementTime.timeIntervalSinceNow
let newPoint = Instrumentation(title, increment, incrementedTime)
elapsedTimes.append(newPoint)
incrementTime = NSDate()
}
用法:-
instrument("View Did Appear")
print("ELAPSED TIMES \(elapsedTimes)")
样例输出:
[MyApp.SomeViewController.]仪器仪表(标题:“开始视图 Did Load", point: 1, elapsedTime: 0.040504038333892822), MyApp.SomeViewController。检测(标题:“完成添加 SubViews", point: 2, elapsedTime: 0.010585010051727295), MyApp.SomeViewController。仪器仪表(标题:“视图已出现”, 点:3,elapsedTime: 0.56564098596572876)]
其他回答
下面是我使用的两个单行宏:
#define TICK NSDate *startTime = [NSDate date]
#define TOCK NSLog(@"Time: %f", -[startTime timeIntervalSinceNow])
像这样使用它:
TICK;
/* ... Do Some Work Here ... */
TOCK;
这里有另一种方法,在Swift中,使用defer关键字来做到这一点
func methodName() {
let methodStart = Date()
defer {
let executionTime = Date().timeIntervalSince(methodStart)
print("Execution time: \(executionTime)")
}
// do your stuff here
}
来自苹果的文档:defer语句用于在将程序控制权转移到该defer语句出现的范围之外之前执行代码。
这类似于try/finally块,优点是将相关代码分组。
我在我的utils库中使用这个(Swift 4.2):
public class PrintTimer {
let start = Date()
let name: String
public init(file: String=#file, line: Int=#line, function: String=#function, name: String?=nil) {
let file = file.split(separator: "/").last!
self.name = name ?? "\(file):\(line) - \(function)"
}
public func done() {
let end = Date()
print("\(self.name) took \((end.timeIntervalSinceReferenceDate - self.start.timeIntervalSinceReferenceDate).roundToSigFigs(5)) s.")
}
}
…然后调用如下方法:
func myFunctionCall() {
let timer = PrintTimer()
// ...
timer.done()
}
…运行后在控制台中看起来是这样的:
MyFile.swift:225 - myFunctionCall() took 1.8623 s.
虽然不像上面的TICK/TOCK那样简洁,但它足以清楚地看到它在做什么,并自动包括正在计时的内容(通过文件、方法开头的行和函数名)。显然,如果我想要更多的细节(例如,如果我不只是计时一个方法调用,因为是通常的情况下,而是在该方法内计时块),我可以在PrintTimer init上添加“name="Foo""参数来命名它除了默认值之外的东西。
好吧,如果你的目标是找出你可以修复什么使它更快,那是一个有点不同的目标。测量函数所花费的时间是一种很好的方法,可以发现您所做的事情是否产生了影响,但要找出该做什么,您需要一种不同的技术。这就是我的建议,我知道你可以在iphone上这么做。
编辑:审稿人建议我详细说明答案,所以我想用一种简单的方式来解释。 你的整个程序需要足够的时钟时间来打扰你。假设这是N秒。 你假设你可以加速它。唯一的方法就是让它在这段时间内不做它正在做的事情,占m秒。 你一开始并不知道这个东西是什么。您可以像所有程序员一样猜测,但它很容易是其他东西。不管是什么,下面是找到它的方法:
因为那个东西,不管它是什么,占了m/N的时间,这意味着如果你随机暂停它,你在它做那件事的时候抓住它的概率是m/N。当然,它可能在做其他事情,但暂停它,看看它在做什么。 现在再做一次。如果你看到它再次做同样的事情,你就更可疑了。
做10次,或者20次。现在,如果你看到它在多次暂停中做一些特定的事情(不管你怎么描述它),你可以摆脱,你知道两件事。你大概知道需要花多少时间,但你很清楚要修复什么。 如果你还想知道能节省多少时间,那很简单。之前测量,修正,之后测量。如果你真的很失望,那就退出修复。
你知道这和测量有什么不同吗?这是发现,而不是测量。大多数分析都是基于尽可能精确地测量所花费的时间,就好像这很重要一样,并明确需要解决的问题。剖析并不能找到所有的问题,但是这种方法确实能找到所有的问题,而那些你没有找到的问题对你造成了伤害。
对于Swift 4,添加一个委托到你的类:
public protocol TimingDelegate: class {
var _TICK: Date?{ get set }
}
extension TimingDelegate {
var TICK: Date {
_TICK = Date()
return(_TICK)!
}
func TOCK(message: String) {
if (_TICK == nil){
print("Call 'TICK' first!")
}
if (message == ""){
print("\(Date().timeIntervalSince(_TICK!))")
}
else{
print("\(message): \(Date().timeIntervalSince(_TICK!))")
}
}
}
加入我们班:
class MyViewcontroller: UIViewController, TimingDelegate
然后添加到你的类:
var _TICK: Date?
当你想为某事计时时,可以从以下开始:
TICK
最后:
TOCK("Timing the XXX routine")
推荐文章
- 如何删除默认的导航栏空间在SwiftUI导航视图
- 如何在iOS中使用Swift编程segue
- Swift -整数转换为小时/分钟/秒
- Swift:声明一个空字典
- 为什么ARC仍然需要@autoreleasepool ?
- 检测浏览器标签是否有焦点
- 在成功提交我的应用程序后,“太多符号文件”
- 首先添加一个UIView,甚至是导航栏
- 就性能而言,使用std::memcpy()还是std::copy()更好?
- 我如何改变UIButton标题颜色?
- 在Swift中如何调用GCD主线程上的参数方法?
- NSLayoutConstraints是可动画的吗?
- iOS -构建失败,CocoaPods无法找到头文件
- Xcode 4挂在“附加到(应用程序名称)”
- CFNetwork SSLHandshake iOS 9失败