import Darwin import Foundation import Localization public struct CPUSampler { private var previousTicks: [[UInt32]] = [] public init() {} public static func topology() -> CPUTopology { let brand = Sysctl.string("machdep.cpu.brand_string") ?? "CPU" let logical = Sysctl.int("hw.logicalcpu") ?? ProcessInfo.processInfo.activeProcessorCount let levels = Sysctl.int("hw.nperflevels") ?? 1 guard levels > 1 else { return CPUTopology(brand: brand, logicalCores: logical, clusters: [CPUCluster(id: 0, name: tr("核心"), coreIndices: Array(0.. 0 else { continue } let raw = Sysctl.string("hw.perflevel\(level).name") ?? "" clusters.append(CPUCluster(id: level, name: localizedClusterName(raw), coreIndices: Array(offset.. String { switch raw.lowercased() { case "super": tr("超级核") case "performance": tr("性能核") case "efficiency": tr("能效核") default: raw.isEmpty ? tr("核心") : raw } } public mutating func sample() -> CPULoad? { var cpuCount: natural_t = 0 var info: processor_info_array_t? var infoCount: mach_msg_type_number_t = 0 let kr = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpuCount, &info, &infoCount) guard kr == KERN_SUCCESS, let info else { return nil } // 内核分配的数组必须归还,否则每次采样都会泄漏 defer { vm_deallocate(mach_task_self_, vm_address_t(bitPattern: info), vm_size_t(Int(infoCount) * MemoryLayout.stride)) } let states = Int(CPU_STATE_MAX) var ticks: [[UInt32]] = [] ticks.reserveCapacity(Int(cpuCount)) for core in 0.. 0 else { return nil } var averages = [Double](repeating: 0, count: 3) let loadCount = getloadavg(&averages, 3) let user = Double(sumUser) / Double(sumAll) let system = Double(sumSystem) / Double(sumAll) return CPULoad(total: min(1, user + system), user: user, system: system, perCore: perCore, loadAverage: loadCount > 0 ? Array(averages.prefix(Int(loadCount))) : []) } }