49

How do I obtain CPU usage for an application? It's definitely possible, because there are application in App store (Activity Monitor Touch) which can show it.

Cœur
  • 37,241
  • 25
  • 195
  • 267
ivanzoid
  • 5,952
  • 2
  • 34
  • 43
  • 1
    You need to find out why `task_info()` is failing and that will help you move on. See the answer to this SO question: http://stackoverflow.com/questions/5182924/where-is-my-ipad-runtime-memory-going. I think it's cos you haven't initialised `port`; use `task_info_self()` instead of `port`. – trojanfoe Nov 22 '11 at 11:25
  • 1
    Wow, thanks for that! Now this code seems to be working. The only correction that we need mach_task_self(), not task_info_self(). – ivanzoid Nov 22 '11 at 12:44
  • 1
    Please write it as an answer. And wait some time, if these is no other good answer, accept it. – Tinyfool Dec 03 '11 at 14:33
  • @jww Already monitor cpu usage successfully by your way; But can you help answer my related questions? https://stackoverflow.com/questions/47071265/how-to-analyze-stack-info-of-a-thread – Paradise Nov 02 '17 at 09:12

3 Answers3

83

Update. This code is working for me:

Update 2. The thread_list was leaking, so added 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;
}
some_id
  • 29,466
  • 62
  • 182
  • 304
ivanzoid
  • 5,952
  • 2
  • 34
  • 43
  • 1
    Does this give CPU usage for the app or overall CPU usage? – Manish Ahuja Aug 07 '12 at 06:08
  • 1
    Thanks for your quick reply. Is there any way I can get the overall CPU usage? – Manish Ahuja Aug 07 '12 at 08:10
  • i use this code to calculate the cpu usage but it always return 0 from this function.. Please help – Saiful Sep 19 '12 at 06:50
  • 4
    is there a way to get cpu usage by process id? – Rukshan Oct 15 '12 at 06:22
  • can we get memory usage of each application? – Amit Khandelwal Jul 30 '15 at 08:13
  • 2
    In the line where the microseconds are added up, the system time is added twice. This should probably be user time + system time instead. – George Aug 26 '15 at 16:46
  • For the Thread calculation I would use += rather than making calculation formula longer, imvho it would be clearer – Julian Oct 02 '15 at 11:50
  • What about with .NET 2.0? is that possible? – Yann Mar 23 '16 at 08:54
  • @Yann this topic is about iOS only (probably will work also on OS X) – ivanzoid Mar 24 '16 at 08:06
  • @ivanzoid What is the unit of the tot_cpu? Is it percent? Thanks. – ZigZagZebra Jun 20 '16 at 19:06
  • The CPU usage found in [Debug Navigator](https://developer.apple.com/library/mac/recipes/xcode_help-debug_navigator/articles/about_debug_navigator.html) of xcode and what this function gives are different. I am wondering why is it so ? – Durai Amuthan.H Jul 20 '16 at 06:37
  • tot_sec and tot_usec are unused. removing these variables has no impact on the function. they should be removed. – Alex Blair Feb 07 '17 at 22:40
  • @Jarryd Thx for mention vm; But can you help answer my related questions? https://stackoverflow.com/questions/47071265/how-to-analyze-stack-info-of-a-thread – Paradise Nov 02 '17 at 09:09
  • @Paradise You should use the time profiler in Instruments and it will show you what functions are using CPU time. Its important you profile before and after your changes and profile a few times. Profile the app running on a device, not the simulator. If e.g. your CPU overload is from a function that repeats calculations, try and store the output in memory first, and read from memory (that's if the calculation is repeated without different results) – some_id Nov 04 '17 at 09:32
  • @Jarryd, yes; But instrument cannot help live app; So I monitor CPU/GPU/Memory and dump stack trace programmatically – Paradise Nov 06 '17 at 02:20
  • you should git tag your releases. – some_id Nov 19 '17 at 21:40
  • hi man, I have a quite trouble question; for "basic_info_th->cpu_usage", what's the real meaning of this cpu_usage? It's represents usage of a second or a period? Why we need to sum up? – Paradise Nov 21 '17 at 07:03
10

For 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
}
Community
  • 1
  • 1
Lionking
  • 570
  • 6
  • 9
  • 2
    I have a question: Is the calculation of the CPU usage of my application, or is it the calculation of the CPU use of the iOS? – Markus Nov 23 '17 at 09:58
  • 3
    Hi Markus, this function return the CPU usage of your application. – Lionking Nov 27 '17 at 02:04
  • 2
    I think the vm_deallocate is incorrect. Certainly in Swift 4 the correct way to call it would be `vm_deallocate(mach_task_self_, vm_address_t(bitPattern: thread_list), vm_size_t(Int(thread_count) * MemoryLayout.stride) )` Accessing thread_list.pointee would return the first value of thread_list, not the address of the array itself. – kuwerty May 11 '18 at 08:57
  • thanks @kuwerty! otherwise it was constantly leaking. – RemembranceNN Apr 13 '22 at 12:48
0

Try this:

- (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];
}

However, that method calculates the percentages based on the starting point of each process. If you are looking for the more traditional way of calculating these numbers, see Petesh's answer.

Coder-256
  • 5,212
  • 2
  • 23
  • 51