如何在 Swift 中测量 DispatchQueue 并发异步中的代码块执行时间?

How to measure code block execution time inside DispatchQueue concurrent async in Swift?

假设我有这种函数和 DispatchQueue 逻辑。假设当 synchLatest() 被调用时它会触发 "Code Block 1" 两次。

在一个循环中,执行 "Code Block 1" 只是从 grpc 响应中检索一个字符串并存储在 UserDefaults 中,这应该是怎么回事 1.7 seconds 和其次,它在 5 seconds?

循环期间执行
let synchQueue = DispatchQueue(label: "com.dmapp.synchQueue", qos: .default, attributes: .concurrent)

let synchProcessQueue = DispatchQueue(label: "com.dmapp.processQueue", qos: .default, attributes: .concurrent)

func synchLatest() {
  while(someconditions) {
    synchQueue.async {
          ...
          let response = try grpcCall.receive()
          ...
          synchProcessQueue.async {
              ....
              measure("Code Block 1", {
                   if response.data.nickname != "" {
                        // Store in UserDefaults
                   }
              })
              ....
          }
    }
  }
}

@discardableResult
static func measure<A>(name: String = "", _ block: () -> A) -> A {
    let startTime = CACurrentMediaTime()
    let result = block()
    let timeElapsed = CACurrentMediaTime() - startTime
    print("Time: \(name) - \(timeElapsed)")
    return result
}

我在这里测量代码执行时间的方式有误吗?

CACurrentMediaTime 是衡量时间的好方法。它的开销很低,不会遇到 DateCFAbsoluteTimeGetCurrent 的问题,这些问题“不保证单调递增的结果。”

基准测试的一些一般准则包括:

  • 让应用在开始基准测试之前达到静止状态;
  • 不要 运行 相互同时进行独立测试(因为它们可能会争用相同的资源);
  • 重复多次;和
  • 更改基准测试的顺序以消除测量中的噪音。

如果您正在寻找手动使用 CACurrentMediaTime 的替代方法,另一种方法是使用 signposts and points of interest,它不仅会记录花费的时间,而且会让您将您的仪器时间线过滤到相关时间段(并且您可能能够诊断出差异的来源)。