objective-ccocoamacos

Get CPU percent usage on macOS


I'm a beginner in Objective-C, and I decided to try to write some simple application, so I'm trying to make an app which would measure CPU usage and such. Is there a simple way to get information such as the CPU percent usage using Objective-C in a Cocoa application?

I have found this question Determine Process Info Programmatically in Darwin/OSX which is similar, but not exactly the same. Mainly, I want the CPU percent usage of the whole system, not just my process, and I would actually prefer an Objective-C solution whereas in that question the poster wanted something else.


Solution

  • Here is the way i did it:

    *.h file:

    #include <sys/sysctl.h>
    #include <sys/types.h>
    #include <mach/mach.h>
    #include <mach/processor_info.h>
    #include <mach/mach_host.h>
    

    ivars:

    processor_info_array_t cpuInfo, prevCpuInfo;
    mach_msg_type_number_t numCpuInfo, numPrevCpuInfo;
    unsigned numCPUs;
    NSTimer *updateTimer;
    NSLock *CPUUsageLock;
    

    *.m file

    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
    {    
        int mib[2U] = { CTL_HW, HW_NCPU };
        size_t sizeOfNumCPUs = sizeof(numCPUs);
        int status = sysctl(mib, 2U, &numCPUs, &sizeOfNumCPUs, NULL, 0U);
        if(status)
            numCPUs = 1;
    
        CPUUsageLock = [[NSLock alloc] init];
    
        updateTimer = [[NSTimer scheduledTimerWithTimeInterval:3
                                                        target:self
                                                      selector:@selector(updateInfo:)
                                                      userInfo:nil
                                                       repeats:YES] retain];    
    }
    
    - (void)updateInfo:(NSTimer *)timer
    {
        natural_t numCPUsU = 0U;
        kern_return_t err = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUsU, &cpuInfo, &numCpuInfo);
        if(err == KERN_SUCCESS) {
            [CPUUsageLock lock];
    
            for(unsigned i = 0U; i < numCPUs; ++i) {
                float inUse, total;
                if(prevCpuInfo) {
                    inUse = (
                             (cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER]   - prevCpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER])
                             + (cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] - prevCpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM])
                             + (cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE]   - prevCpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE])
                             );
                    total = inUse + (cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE] - prevCpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE]);
                } else {
                    inUse = cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_USER] + cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_SYSTEM] + cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_NICE];
                    total = inUse + cpuInfo[(CPU_STATE_MAX * i) + CPU_STATE_IDLE];
                }
    
                NSLog(@"Core: %u Usage: %f",i,inUse / total);
            }
            [CPUUsageLock unlock];
    
            if(prevCpuInfo) {
                size_t prevCpuInfoSize = sizeof(integer_t) * numPrevCpuInfo;
                vm_deallocate(mach_task_self(), (vm_address_t)prevCpuInfo, prevCpuInfoSize);
            }
    
            prevCpuInfo = cpuInfo;
            numPrevCpuInfo = numCpuInfo;
    
            cpuInfo = NULL;
            numCpuInfo = 0U;
        } else {
            NSLog(@"Error!");
            [NSApp terminate:nil];
        }
    }