【问题标题】:iOS - Get CPU usage from applicationiOS - 从应用程序获取 CPU 使用率
【发布时间】:2012-01-03 15:11:23
【问题描述】:

有谁知道如何获取应用程序的 CPU 使用率?绝对有可能,因为应用商店里有应用程序(Activity Monitor Touch)可以显示。

【问题讨论】:

  • 您需要找出task_info() 失败的原因,这将帮助您继续前进。请参阅此 SO 问题的答案:stackoverflow.com/questions/5182924/…。我想是因为你还没有初始化port;使用task_info_self() 而不是port
  • 哇,谢谢!现在这段代码似乎正在工作。我们需要的唯一修正是 mach_task_self(),而不是 task_info_self()。
  • 请把它写成答案。稍等片刻,如果没有其他好的答案,请接受。
  • @jww 已经通过你的方式成功监控cpu使用情况;但是你能帮忙回答我的相关问题吗? stackoverflow.com/questions/47071265/…

标签: iphone objective-c ios xcode cpu-usage


【解决方案1】:

对于 Swift 3:

fileprivate func cpuUsage() -> Double {
    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: Double = 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)
            if kr != KERN_SUCCESS {
                return -1
            }

            let threadBasicInfo = convertThreadInfoToThreadBasicInfo(thinfo)

            if threadBasicInfo.flags != TH_FLAGS_IDLE {
                tot_cpu += (Double(threadBasicInfo.cpu_usage) / Double(TH_USAGE_SCALE)) * 100.0
            }
        } // for each thread
    }

    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
}

【讨论】:

  • 我有一个问题:是计算我的应用程序的CPU使用率,还是计算iOS的CPU使用率?
  • 嗨,Markus,此函数返回您的应用程序的 CPU 使用率。
  • 我认为 vm_deallocate 不正确。当然,在 Swift 4 中调用它的正确方法是 vm_deallocate(mach_task_self_, vm_address_t(bitPattern: thread_list), vm_size_t(Int(thread_count) * MemoryLayout&lt;thread_t&gt;.stride) ) 访问 thread_list.pointee 将返回 thread_list 的第一个值,而不是数组本身的地址。
【解决方案2】:

试试这个:

- (NSString *)cpuUsage
{
   kern_return_t kr;
   task_info_data_t tinfo;
   mach_msg_type_number_t task_info_count;

   task_info_count = TASK_INFO_MAX;
   kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count);
   if (kr != KERN_SUCCESS)
   {
     return @"NA";
   }

   task_basic_info_t      basic_info;
   thread_array_t         thread_list;
   mach_msg_type_number_t thread_count;
   thread_info_data_t     thinfo;
   mach_msg_type_number_t thread_info_count;
   thread_basic_info_t basic_info_th;
   uint32_t stat_thread = 0; // Mach threads

   basic_info = (task_basic_info_t)tinfo;

   // get threads in the task
   kr = task_threads(mach_task_self(), &thread_list, &thread_count);
   if (kr != KERN_SUCCESS)
   {
      return @"NA";
   }
   if (thread_count > 0)
    stat_thread += thread_count;

   long tot_idle = 0;
   long tot_user = 0;
   long tot_kernel = 0;
   int j;

   for (j = 0; j < thread_count; j++)
   {
      thread_info_count = THREAD_INFO_MAX;
      kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
                     (thread_info_t)thinfo, &thread_info_count);
      if (kr != KERN_SUCCESS)
      {
          return nil;
      }

      basic_info_th = (thread_basic_info_t)thinfo;

      if (basic_info_th->flags & TH_FLAGS_IDLE)
      {
          //This is idle
          tot_idle = tot_idle + basic_info_th->user_time.microseconds + basic_info_th->system_time.microseconds;
      } else {
          //This is user
          tot_user = tot_user + basic_info_th->user_time.microseconds;

          //This is kernel
          tot_kernel = tot_kernel + basic_info_th->system_time.microseconds;
      }

  } // for each thread

  kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t));
  assert(kr == KERN_SUCCESS);

  long tot_cpu = tot_idle + tot_user + tot_kernel

  return [NSString stringWithFormat:@"Idle: %.2f, User: %.2f, Kernel: %.2f", tot_idle/tot_cpu, tot_user/tot_cpu, tot_kernel/tot_cpu];
}

但是,该方法会根据每个流程的起点计算百分比。如果您正在寻找计算这些数字的更传统方法,请参阅Petesh's answer

【讨论】:

    【解决方案3】:

    更新。这段代码对我有用:

    更新 2。 thread_list 泄漏了,所以添加了 vm_deallocate

    #import <mach/mach.h>
    #import <assert.h>
    
    float cpu_usage()
    {
        kern_return_t kr;
        task_info_data_t tinfo;
        mach_msg_type_number_t task_info_count;
    
        task_info_count = TASK_INFO_MAX;
        kr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)tinfo, &task_info_count);
        if (kr != KERN_SUCCESS) {
            return -1;
        }
    
        task_basic_info_t      basic_info;
        thread_array_t         thread_list;
        mach_msg_type_number_t thread_count;
    
        thread_info_data_t     thinfo;
        mach_msg_type_number_t thread_info_count;
    
        thread_basic_info_t basic_info_th;
        uint32_t stat_thread = 0; // Mach threads
    
        basic_info = (task_basic_info_t)tinfo;
    
        // get threads in the task
        kr = task_threads(mach_task_self(), &thread_list, &thread_count);
        if (kr != KERN_SUCCESS) {
            return -1;
        }
        if (thread_count > 0)
            stat_thread += thread_count;
    
        long tot_sec = 0;
        long tot_usec = 0;
        float tot_cpu = 0;
        int j;
    
        for (j = 0; j < (int)thread_count; j++)
        {
            thread_info_count = THREAD_INFO_MAX;
            kr = thread_info(thread_list[j], THREAD_BASIC_INFO,
                             (thread_info_t)thinfo, &thread_info_count);
            if (kr != KERN_SUCCESS) {
                return -1;
            }
    
            basic_info_th = (thread_basic_info_t)thinfo;
    
            if (!(basic_info_th->flags & TH_FLAGS_IDLE)) {
                tot_sec = tot_sec + basic_info_th->user_time.seconds + basic_info_th->system_time.seconds;
                tot_usec = tot_usec + basic_info_th->user_time.microseconds + basic_info_th->system_time.microseconds;
                tot_cpu = tot_cpu + basic_info_th->cpu_usage / (float)TH_USAGE_SCALE * 100.0;
            }
    
        } // for each thread
    
        kr = vm_deallocate(mach_task_self(), (vm_offset_t)thread_list, thread_count * sizeof(thread_t));
        assert(kr == KERN_SUCCESS);
    
        return tot_cpu;
    }
    

    【讨论】:

    • 这是否给出了应用程序的 CPU 使用率或整体 CPU 使用率?
    • 感谢您的快速回复。有什么方法可以获取整体 CPU 使用率?
    • 我使用这段代码来计算cpu使用率,但它总是从这个函数返回0..请帮助
    • 有没有办法通过进程ID获取cpu使用率?
    • 微秒加起来的那一行,系统时间加了两次。这可能应该是用户时间 + 系统时间。
    猜你喜欢
    • 2017-11-28
    • 1970-01-01
    • 2011-06-28
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 2015-07-22
    相关资源
    最近更新 更多