mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 00:04:15 +09:00
109 lines
3.9 KiB
Swift
109 lines
3.9 KiB
Swift
//
|
|
// reader.swift
|
|
// Stats
|
|
//
|
|
// Created by Serhiy Mytrovtsiy on 01.06.2019.
|
|
// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
class CPUReader: Reader {
|
|
var value: Observable<[Double]>!
|
|
var available: Bool = true
|
|
var cpuInfo: processor_info_array_t!
|
|
var prevCpuInfo: processor_info_array_t?
|
|
var numCpuInfo: mach_msg_type_number_t = 0
|
|
var numPrevCpuInfo: mach_msg_type_number_t = 0
|
|
var numCPUs: uint = 0
|
|
var updateTimer: Timer!
|
|
let CPUUsageLock: NSLock = NSLock()
|
|
|
|
var perCoreMode: Bool = false
|
|
|
|
init() {
|
|
let mibKeys: [Int32] = [ CTL_HW, HW_NCPU ]
|
|
self.value = Observable([])
|
|
mibKeys.withUnsafeBufferPointer() { mib in
|
|
var sizeOfNumCPUs: size_t = MemoryLayout<uint>.size
|
|
let status = sysctl(processor_info_array_t(mutating: mib.baseAddress), 2, &numCPUs, &sizeOfNumCPUs, nil, 0)
|
|
if status != 0 {
|
|
numCPUs = 1
|
|
}
|
|
read()
|
|
}
|
|
}
|
|
|
|
func start() {
|
|
if updateTimer != nil {
|
|
return
|
|
}
|
|
updateTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(read), userInfo: nil, repeats: true)
|
|
}
|
|
|
|
func stop() {
|
|
if updateTimer == nil {
|
|
return
|
|
}
|
|
updateTimer.invalidate()
|
|
updateTimer = nil
|
|
}
|
|
|
|
@objc func read() {
|
|
var numCPUsU: natural_t = 0
|
|
let err: kern_return_t = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &numCPUsU, &cpuInfo, &numCpuInfo);
|
|
if err == KERN_SUCCESS {
|
|
CPUUsageLock.lock()
|
|
|
|
var inUseOnAllCores: Int32 = 0
|
|
var totalOnAllCores: Int32 = 0
|
|
var usagePerCore: [Double] = []
|
|
|
|
for i in 0 ..< Int32(numCPUs) {
|
|
var inUse: Int32
|
|
var total: Int32
|
|
if let prevCpuInfo = prevCpuInfo {
|
|
inUse = cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_USER)]
|
|
- prevCpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_USER)]
|
|
+ cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_SYSTEM)]
|
|
- prevCpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_SYSTEM)]
|
|
+ cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_NICE)]
|
|
- prevCpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_NICE)]
|
|
total = inUse + (cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_IDLE)]
|
|
- prevCpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_IDLE)])
|
|
} else {
|
|
inUse = cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_USER)]
|
|
+ cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_SYSTEM)]
|
|
+ cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_NICE)]
|
|
total = inUse + cpuInfo[Int(CPU_STATE_MAX * i + CPU_STATE_IDLE)]
|
|
}
|
|
|
|
inUseOnAllCores = inUseOnAllCores + inUse
|
|
totalOnAllCores = totalOnAllCores + total
|
|
usagePerCore.insert((Double(inUse) / Double(total)), at: Int(i))
|
|
}
|
|
|
|
if self.perCoreMode {
|
|
self.value << usagePerCore
|
|
} else {
|
|
self.value << [(Double(inUseOnAllCores) / Double(totalOnAllCores))]
|
|
}
|
|
|
|
CPUUsageLock.unlock()
|
|
|
|
if let prevCpuInfo = prevCpuInfo {
|
|
let prevCpuInfoSize: size_t = MemoryLayout<integer_t>.stride * Int(numPrevCpuInfo)
|
|
vm_deallocate(mach_task_self_, vm_address_t(bitPattern: prevCpuInfo), vm_size_t(prevCpuInfoSize))
|
|
}
|
|
|
|
prevCpuInfo = cpuInfo
|
|
numPrevCpuInfo = numCpuInfo
|
|
|
|
cpuInfo = nil
|
|
numCpuInfo = 0
|
|
} else {
|
|
print("Error KERN_SUCCESS!")
|
|
}
|
|
}
|
|
}
|