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.
Asked
Active
Viewed 4.7k times
49
-
1You 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
-
1Wow, 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
-
1Please 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 Answers
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;
}
-
1
-
1Thanks 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
-
-
2In 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
-
-
-
-
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
-
-
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
}
-
2I 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
-
2I 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 -
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