stats
stats
是菜单栏中的 macos 系统监视器。
github上的地址在这里。
stats
是一个允许您监控 macos 系统的应用程序。macos 10.13 (high sierra)
及更高版本目前支持统计信息。
安装
手动安装
您可以在此处下载最新版本。
这将下载一个名为stats.dmg
. 打开它并将应用程序移动到应用程序文件夹。
homebrew
要使用 homebrew 安装它,请打开终端应用程序并键入:
brew install --cask stats
stats
是一个允许您监控 macos
系统的应用程序。
- 电池电量
- 蓝牙设备
- cpu 利用率
- 磁盘利用率
- 风扇控制
- gpu 利用率
- 内存使用情况
- 网络使用情况
- 传感器信息(温度/电压/功率)
如何减少 stats 的能源影响或 cpu 使用率?
stats 尽可能提高效率。但是定期读取一些数据并不是一项便宜的任务。每个模块都有自己的“价格”。因此,如果您想减少 stats 对能源的影响,您需要禁用一些 stats 模块。效率最低的模块是传感器和蓝牙。在某些情况下,禁用这些模块最多可将 cpu 使用率和电源效率降低 50%。
主要代码分析
stats
程序基本上是使用swift
写成,代码量并不多,如果是刚学习swift
的可以以这个为demo
来进行相应的学习,从中可以体会到macos
的编程基础,而swift
在这个项目中的结构也非常的清晰,通过这个项目,相信对swift
的使用会有更进一步的了解。
cpu显示
获取cpu
相关信息,通过函数获取到相关的信息,通过计算得出了要显示的内容,显示在相应的位置上,这个是整个代码的核心功能,因为stat
最重要的一点是展示系统的信息。
public override func read() {
let result: kern_return_t = host_processor_info(mach_host_self(), processor_cpu_load_info, &self.numcpusu, &self.cpuinfo, &self.numcpuinfo)
if result == kern_success {
self.cpuusagelock.lock()
self.usagepercore = []
for i in 0 ..< int32(numcpus) {
var inuse: int32
var total: int32
if let prevcpuinfo = self.prevcpuinfo {
inuse = self.cpuinfo[int(cpu_state_max * i + cpu_state_user)]
- prevcpuinfo[int(cpu_state_max * i + cpu_state_user)]
+ self.cpuinfo[int(cpu_state_max * i + cpu_state_system)]
- prevcpuinfo[int(cpu_state_max * i + cpu_state_system)]
+ self.cpuinfo[int(cpu_state_max * i + cpu_state_nice)]
- prevcpuinfo[int(cpu_state_max * i + cpu_state_nice)]
total = inuse + (self.cpuinfo[int(cpu_state_max * i + cpu_state_idle)]
- prevcpuinfo[int(cpu_state_max * i + cpu_state_idle)])
} else {
inuse = self.cpuinfo[int(cpu_state_max * i + cpu_state_user)]
+ self.cpuinfo[int(cpu_state_max * i + cpu_state_system)]
+ self.cpuinfo[int(cpu_state_max * i + cpu_state_nice)]
total = inuse + self.cpuinfo[int(cpu_state_max * i + cpu_state_idle)]
}
if total != 0 {
self.usagepercore.append(double(inuse) / double(total))
}
}
self.cpuusagelock.unlock()
let showhyperthratedcores = store.shared.bool(key: "cpu_hyperhreading", defaultvalue: false)
if showhyperthratedcores || !self.hashyperthreadingcores {
self.response.usagepercore = self.usagepercore
} else {
var i = 0
var a = 0
self.response.usagepercore = []
while i < int(self.usagepercore.count/2) {
a = i*2
if self.usagepercore.indices.contains(a) && self.usagepercore.indices.contains(a+1) {
self.response.usagepercore.append((double(self.usagepercore[a]) + double(self.usagepercore[a+1])) / 2)
}
i += 1
}
}
if let prevcpuinfo = self.prevcpuinfo {
let prevcpuinfosize: size_t = memorylayout<integer_t>.stride * int(self.numprevcpuinfo)
vm_deallocate(mach_task_self_, vm_address_t(bitpattern: prevcpuinfo), vm_size_t(prevcpuinfosize))
}
self.prevcpuinfo = self.cpuinfo
self.numprevcpuinfo = self.numcpuinfo
self.cpuinfo = nil
self.numcpuinfo = 0
} else {
error("host_processor_info(): \(string(cstring: mach_error_string(result), encoding: string.encoding.ascii) ?? "unknown error")", log: self.log)
}
let cpuinfo = hostcpuloadinfo()
if cpuinfo == nil {
self.callback(nil)
return
}
let userdiff = double(cpuinfo!.cpu_ticks.0 - self.previousinfo.cpu_ticks.0)
let sysdiff = double(cpuinfo!.cpu_ticks.1 - self.previousinfo.cpu_ticks.1)
let idlediff = double(cpuinfo!.cpu_ticks.2 - self.previousinfo.cpu_ticks.2)
let nicediff = double(cpuinfo!.cpu_ticks.3 - self.previousinfo.cpu_ticks.3)
let totalticks = sysdiff + userdiff + nicediff + idlediff
let system = sysdiff / totalticks
let user = userdiff / totalticks
let idle = idlediff / totalticks
if !system.isnan {
self.response.systemload = system
}
if !user.isnan {
self.response.userload = user
}
if !idle.isnan {
self.response.idleload = idle
}
self.previousinfo = cpuinfo!
self.response.totalusage = self.response.systemload + self.response.userload
self.callback(self.response)
}
电池信息
对于macos
的系统来说,用的比较多的还是属于笔记本系列,这样电池在整个系统来说,占了一个相关重要的作用,电量的显示可以让我们放心的去做工作。如果担心这块软件较为费点,可以参考上面的说明。
获取电池信息:
public override func read() {
let psinfo = iopscopypowersourcesinfo().takeretainedvalue()
let pslist = iopscopypowersourceslist(psinfo).takeretainedvalue() as [cftyperef]
if pslist.isempty {
return
}
for ps in pslist {
if let list = iopsgetpowersourcedescription(psinfo, ps).takeunretainedvalue() as? [string: any] {
self.usage.powersource = list[kiopspowersourcestatekey] as? string ?? "ac power"
self.usage.ischarged = list[kiopsischargedkey] as? bool ?? false
self.usage.ischarging = self.getboolvalue("ischarging" as cfstring) ?? false
self.usage.level = double(list[kiopscurrentcapacitykey] as? int ?? 0) / 100
if let time = list[kiopstimetoemptykey] as? int {
self.usage.timetoempty = int(time)
}
if let time = list[kiopstimetofullchargekey] as? int {
self.usage.timetocharge = int(time)
}
if self.usage.powersource == "ac power" {
self.usage.timeonacpower = date()
}
self.usage.cycles = self.getintvalue("cyclecount" as cfstring) ?? 0
self.usage.designedcapacity = self.getintvalue("designcapacity" as cfstring) ?? 1
self.usage.maxcapacity = self.getintvalue((isarm ? "applerawmaxcapacity" : "maxcapacity") as cfstring) ?? 1
if !isarm {
self.usage.state = list[kiopsbatteryhealthkey] as? string
}
self.usage.health = int((double(100 * self.usage.maxcapacity) / double(self.usage.designedcapacity)).rounded(.tonearestoreven))
self.usage.amperage = self.getintvalue("amperage" as cfstring) ?? 0
self.usage.voltage = self.getvoltage() ?? 0
self.usage.temperature = self.gettemperature() ?? 0
var acwatts: int = 0
if let acdetails = iopscopyexternalpoweradapterdetails() {
if let aclist = acdetails.takeretainedvalue() as? [string: any] {
guard let watts = aclist[kiopspoweradapterwattskey] else {
return
}
acwatts = int(watts as! int)
}
}
self.usage.acwatts = acwatts
self.callback(self.usage)
}
}
}
发表评论