首页 > 解决方案 > 如何使用swift最新版本计算ios中APP的cpu使用率?我现在在 xCode 11 上

问题描述

我目前正在使用此代码:

public func cpuUsage(_ cpuModel:CpuIosModel?) -> Float { guard let cpuModel = cpuModel else {

        print("cpuUsage is empty")
        return -1
    }

    var kr: kern_return_t
    var task_info_count: mach_msg_type_number_t
   
    task_info_count = mach_msg_type_number_t(TASK_INFO_MAX)
    var tinfo = [integer_t](repeating: 0, count: Int(task_info_count))

    kr = task_info(mach_task_self_, task_flavor_t(TASK_BASIC_INFO), &tinfo, &task_info_count)
    if kr != KERN_SUCCESS {
        return -1
    }

    var thread_list: thread_act_array_t? = UnsafeMutablePointer(mutating: [thread_act_t]())
    var thread_count: mach_msg_type_number_t = 0
    defer {
        if let thread_list = thread_list {
            vm_deallocate(mach_task_self_, vm_address_t(UnsafePointer(thread_list).pointee), vm_size_t(thread_count))
        }
    }
    kr = task_threads(mach_task_self_, &thread_list, &thread_count)

    if kr != KERN_SUCCESS {

        return -1
    }

    var tot_cpu: Float = 0
    var usr_space_time: Int = 0      //time in ms
    var system_space_time:Int = 0    //time in ms
    var thread_sleep_time: Int = 0   // time in sec
    var counter:Int = 0

    if let thread_list = thread_list {

        for j in 0 ..< Int(thread_count) {
            var thread_info_count = mach_msg_type_number_t(THREAD_INFO_MAX)
            var thinfo = [integer_t](repeating: 0, count: Int(thread_info_count))
            kr = thread_info(thread_list[j], thread_flavor_t(THREAD_BASIC_INFO),
                             &thinfo, &thread_info_count)

            let threadBasicInfo = convertThreadInfoToThreadBasicInfo(thinfo)

            if threadBasicInfo.flags != TH_FLAGS_IDLE {
                tot_cpu += (Float(threadBasicInfo.cpu_usage) / Float(TH_USAGE_SCALE)) * 100.0
                usr_space_time += Int(threadBasicInfo.user_time.microseconds/1000)
                system_space_time += Int(threadBasicInfo.system_time.microseconds/1000)
                thread_sleep_time += Int(threadBasicInfo.sleep_time)
                counter = counter + 1
            }
           

        } // for each thread

        if counter != 0 {
            //setCpuData(tot_cpu,usr_space_time,system_space_time)
            setCpuData(tot_cpu: tot_cpu, usr_space_time: usr_space_time, system_space_time: system_space_time, thread_sleep_time: thread_sleep_time,cpuModel: cpuModel)
            print(usr_space_time)
            return -1
        }
    }
    return tot_cpu
}

fileprivate func convertThreadInfoToThreadBasicInfo(_ threadInfo: [integer_t]) -> thread_basic_info {
    var result = thread_basic_info()
    result.user_time = time_value_t(seconds: threadInfo[0], microseconds: threadInfo[1])
    result.system_time = time_value_t(seconds: threadInfo[2], microseconds: threadInfo[3])
    result.cpu_usage = threadInfo[4]
    result.policy = threadInfo[5]
    result.run_state = threadInfo[6]
    result.flags = threadInfo[7]
    result.suspend_count = threadInfo[8]
    result.sleep_time = threadInfo[9]
    return result
}

但这总是将 tot_cpu 设为 0。如果您有工作代码,请提供帮助。我也从互联网上得到了这段代码。有人可以解释为什么 convertThreadInfoToThreadBasicInfo() 函数中的 threadInfo[4] 持有 cpu 使用值。这是预先定义的事情吗。

标签: iosswiftxcodecpu-usagexctest

解决方案


我不确定这是否是您要查找的内容,但您可以查看此实现:

func cpuUsage() -> Double {
  var totalUsageOfCPU: Double = 0.0
  var threadsList = UnsafeMutablePointer(mutating: [thread_act_t]())
  var threadsCount = mach_msg_type_number_t(0)
  let threadsResult = withUnsafeMutablePointer(to: &threadsList) {
    return $0.withMemoryRebound(to: thread_act_array_t?.self, capacity: 1) {
      task_threads(mach_task_self_, $0, &threadsCount)
    }
  }
  
  if threadsResult == KERN_SUCCESS {
    for index in 0..<threadsCount {
      var threadInfo = thread_basic_info()
      var threadInfoCount = mach_msg_type_number_t(THREAD_INFO_MAX)
      let infoResult = withUnsafeMutablePointer(to: &threadInfo) {
        $0.withMemoryRebound(to: integer_t.self, capacity: 1) {
          thread_info(threadsList[Int(index)], thread_flavor_t(THREAD_BASIC_INFO), $0, &threadInfoCount)
        }
      }
      
      guard infoResult == KERN_SUCCESS else {
        break
      }
      
      let threadBasicInfo = threadInfo as thread_basic_info
      if threadBasicInfo.flags & TH_FLAGS_IDLE == 0 {
        totalUsageOfCPU = (totalUsageOfCPU + (Double(threadBasicInfo.cpu_usage) / Double(TH_USAGE_SCALE) * 100.0))
      }
    }
  }
  
  vm_deallocate(mach_task_self_, vm_address_t(UInt(bitPattern: threadsList)), vm_size_t(Int(threadsCount) * MemoryLayout<thread_t>.stride))
  return totalUsageOfCPU
}

参考: https ://github.com/dani-gavrilov/GDPerformanceView-Swift/blob/1ee9895fa9279c9858e2b72c3eea579608bf7597/GDPerformanceView-Swift/GDPerformanceMonitoring/Performance%D0%A1alculator.swift#L94


推荐阅读