How to get overall CPU usage in iOS Swift 4.x

i0S Swift Issue

The code below will help you get the CPU usage values. It is useful to build a log system for your iOS application with Swift.

What is a CPU tick?

tick is an arbitrary unit for measuring internal system time. There is usually an OS-internal counter for ticks; the current time and date used by various functions of the OS are derived from that counter.

How many milliseconds a tick represents depends on the OS, and may even vary between installations. Use the OS’s mechanisms to convert ticks into seconds.

  • On MS Windows, there are 10,000 ticks in a millisecond (see http://msdn.microsoft.com/en-us/library/system.datetime.ticks.aspx ).
  • On Linux, the number of clock ticks per second can be obtained using sysconf(_SC_CLK_TCK);. See e.g. http://linux.die.net/man/2/times

As to why a thread reports it’s not being called: That will depend on whether the thread is blocking somewhere (waiting, I/O etc.). If it is not blocking, then yes, the OS’s scheduler will decide when it gets to run, which may be a long time if the system is busy.

Get overall CPU usage not of a single app

The CPU statistics is obtained by calling host_statistics() and the “flavor” argument must be HOST_CPU_LOAD_INFO. hostInfo contains the pointer to the allocated structure, so that value must be rebound, not the address of the variable.

func CPULoadInfo() -> host_cpu_load_info? {
        
        let  HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride / MemoryLayout<integer_t>.stride
        
        var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT)
        let hostInfo = host_cpu_load_info_t.allocate(capacity: 1)
        
        let result = hostInfo.withMemoryRebound(to: integer_t.self, capacity: HOST_CPU_LOAD_INFO_COUNT) {
            host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size)
        }
        
        if result != KERN_SUCCESS{
            print("Error  - \(#file): \(#function) - kern_result_t = \(result)")
            return nil
        }
        let data = hostInfo.move()
        hostInfo.deallocate()
        return data
    }

Alternatively, use a local variable instead of allocating and releasing the host_cpu_load_info structure:

 func hostCPULoadInfo() -> host_cpu_load_info? {
        let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride/MemoryLayout<integer_t>.stride
        var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT)
        var cpuLoadInfo = host_cpu_load_info()
        
        let result = withUnsafeMutablePointer(to: &cpuLoadInfo) {
            $0.withMemoryRebound(to: integer_t.self, capacity: HOST_CPU_LOAD_INFO_COUNT) {
                host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size)
            }
        }
        if result != KERN_SUCCESS{
            print("Error  - \(#file): \(#function) - kern_result_t = \(result)")
            return nil
        }
        return cpuLoadInfo
    }

Result Log: