Files
gentpan 3caf690987 CPU 与内存详情改为 OpenStats 自己的设计:热力图、水位条、压力走势与按应用汇总
- CPU:占用、状态、30 秒变化与温度余量;核心热力图;核心分工与最忙核心;排队程度(每核平均负载与趋势);按应用汇总
- 内存:还可用多少与压力走势条;内存水位条;压缩省下的内存、压缩比与交换区实时读写;按应用汇总
- 数据层新增各核心占用历史、内存压力历史、压缩前大小与交换区换入换出累计量;进程采样返回全部可读进程
- 去掉仿 Stats 的圆环与仪表组件
2026-09-13 06:13:32 +05:00

49 lines
2.1 KiB
Swift

import Darwin
import Foundation
public struct MemorySampler {
private let total = ProcessInfo.processInfo.physicalMemory
private let pageSize: UInt64 = {
var size: vm_size_t = 0
host_page_size(mach_host_self(), &size)
return UInt64(size)
}()
public init() {}
public func sample() -> MemoryUsage? {
var stats = vm_statistics64()
var count = mach_msg_type_number_t(MemoryLayout<vm_statistics64_data_t>.stride / MemoryLayout<integer_t>.stride)
let kr = withUnsafeMutablePointer(to: &stats) {
$0.withMemoryRebound(to: integer_t.self, capacity: Int(count)) {
host_statistics64(mach_host_self(), HOST_VM_INFO64, $0, &count)
}
}
guard kr == KERN_SUCCESS else { return nil }
// 与“活动监视器”口径一致:App 内存 = internal - purgeable
let internalPages = UInt64(stats.internal_page_count)
let purgeable = UInt64(stats.purgeable_count)
let app = (internalPages > purgeable ? internalPages - purgeable : 0) * pageSize
var swap = xsw_usage()
var swapSize = MemoryLayout<xsw_usage>.size
let hasSwap = sysctlbyname("vm.swapusage", &swap, &swapSize, nil, 0) == 0
let swapUsed = hasSwap ? swap.xsu_used : 0
let swapTotal = hasSwap ? swap.xsu_total : 0
let level = Sysctl.int("kern.memorystatus_vm_pressure_level") ?? 1
return MemoryUsage(total: total,
app: app,
wired: UInt64(stats.wire_count) * pageSize,
compressed: UInt64(stats.compressor_page_count) * pageSize,
cached: (UInt64(stats.external_page_count) + purgeable) * pageSize,
swapUsed: swapUsed,
swapTotal: swapTotal,
pressure: MemoryPressure(rawValue: level) ?? .normal,
uncompressed: stats.total_uncompressed_pages_in_compressor * pageSize,
swapInBytes: stats.swapins * pageSize,
swapOutBytes: stats.swapouts * pageSize)
}
}