如何对Swift代码执行进行基准测试?

iel*_*ani 61 performance swift

是否有一种方法/软件可以提供执行用Swift编写的代码块所需的精确时间,除了以下内容?

let date_start = NSDate()

// Code to be executed 

println("\(-date_start.timeIntervalSinceNow)")
Run Code Online (Sandbox Code Playgroud)

Bra*_*son 112

如果你只想要一个代码块的独立计时功能,我使用以下Swift辅助函数:

func printTimeElapsedWhenRunningCode(title:String, operation:()->()) {
    let startTime = CFAbsoluteTimeGetCurrent()
    operation()
    let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
    print("Time elapsed for \(title): \(timeElapsed) s.")
}

func timeElapsedInSecondsWhenRunningCode(operation: ()->()) -> Double {
    let startTime = CFAbsoluteTimeGetCurrent()
    operation()
    let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
    return Double(timeElapsed)
}
Run Code Online (Sandbox Code Playgroud)

前者将注销给定代码段所需的时间,后者将其作为float返回.作为第一个变体的示例:

printTimeElapsedWhenRunningCode(title:"map()") {
    let resultArray1 = randoms.map { pow(sin(CGFloat($0)), 10.0) }
}
Run Code Online (Sandbox Code Playgroud)

将注销如下内容:

map()经过的时间:0.0617449879646301 s

请注意,Swift基准测试将根据您选择的优化级别而有很大差异,因此这可能仅对Swift执行时间的相对比较有用.即使这可能会在每个beta版本的基础上发生变化.

  • 谢谢您的回答非常有帮助 (2认同)

kvi*_*ver 33

如果您希望深入了解某个代码块的性能并确保在编辑时性能不会受到影响,那么最好的方法就是使用XCTest的测量性能函数,例如measure(_ block: () -> Void).

编写一个单元测试来执行您想要进行基准测试的方法,并且该单元测试将多次运行它,为您提供所需的时间和结果的偏差

func testExample() {

    self.measure {
        //do something you want to measure
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以在使用Xcode测试 - >性能测试中找到苹果文档中的更多信息

  • 请注意`measureBlock`将多次执行块代码以获得更好的统计信息. (5认同)

Ixx*_*Ixx 13

您可以使用此函数来测量异步代码和同步代码:

import Foundation

func measure(_ title: String, block: (@escaping () -> ()) -> ()) {

    let startTime = CFAbsoluteTimeGetCurrent()

    block {
        let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
        print("\(title):: Time: \(timeElapsed)")
    }
}
Run Code Online (Sandbox Code Playgroud)

所以基本上你传递一个接受函数作为参数的块,用于告诉测量何时完成.

例如,要测量一些名为"myAsyncCall"的调用所需的时间,您可以这样称呼它:

measure("some title") { finish in
    myAsyncCall {
        finish()
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

对于同步代码:

measure("some title") { finish in
     // code to benchmark
     finish()
     // ...
}
Run Code Online (Sandbox Code Playgroud)

这应该类似于XCTest中的measureBlock,虽然我不知道它是如何在那里实现的.


Noa*_*der 5

基准测试功能-Swift 4.2

这是一种用途广泛的基准测试功能,可以对测试进行标记,执行许多测试并平均其执行时间,在测试之间调用设置块(即,在测量排序算法的过程之间对数组进行改组),清晰地打印基准测试结果,并且还将平均执行时间返回为Double

请尝试以下操作:

@_transparent @discardableResult public func measure(label: String? = nil, tests: Int = 1, printResults output: Bool = true, setup: @escaping () -> Void = { return }, _ block: @escaping () -> Void) -> Double {

    guard tests > 0 else { fatalError("Number of tests must be greater than 0") }

    var avgExecutionTime : CFAbsoluteTime = 0
    for _ in 1...tests {
        setup()
        let start = CFAbsoluteTimeGetCurrent()
        block()
        let end = CFAbsoluteTimeGetCurrent()
        avgExecutionTime += end - start
    }

    avgExecutionTime /= CFAbsoluteTime(tests)

    if output {
        let avgTimeStr = "\(avgExecutionTime)".replacingOccurrences(of: "e|E", with: " × 10^", options: .regularExpression, range: nil)

        if let label = label {
            print(label, "?")
            print("\tExecution time: \(avgTimeStr)s")
            print("\tNumber of tests: \(tests)\n")
        } else {
            print("Execution time: \(avgTimeStr)s")
            print("Number of tests: \(tests)\n")
        }
    }

    return avgExecutionTime
}
Run Code Online (Sandbox Code Playgroud)

用法

var arr = Array(1...1000).shuffled()

measure(label: "Map to String") {
    let _ = arr.map { String($0) }
}

measure(label: "Apple Shuffle", tests: 1000, setup: { arr.shuffle() }) {
    arr.sort()
}

measure {
    let _ = Int.random(in: 1...10000)
}

let mathExecutionTime = measure(printResults: false) {
    let _ = 219 * 354
}

print("Math Execution Time: \(mathExecutionTime * 1000)ms")


// Prints:
//
// Map to String ?
//     Execution time: 0.021643996238708496s
//     Number of tests: 1
//
// Apple's Sorting Method ?
//     Execution time: 0.0010601345300674438s
//     Number of tests: 1000
//
// Execution time: 6.198883056640625 × 10^-05s
// Number of tests: 1
//
// Math Execution Time: 0.016927719116210938ms
//
Run Code Online (Sandbox Code Playgroud)

注意: measure还返回执行时间。的labeltestssetup参数都是可选的。该printResults参数true默认设置为。