如何使用Swift最新版本计算iOS中APP的CPU使用率?截至目前,我使用的是xCode 11

问题描述

我当前正在使用此代码

public func cpuUsage(_ cpuModel:cpuIosModel?)->浮动{ 警卫让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使用率值。这是预定义的东西吗?

解决方法

我不确定这是否是您要寻找的,但是您可以看一下此实现:

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),&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