把电量画成一条河
MenuCue 的 Power 页:一份一直是空的唤醒列表,一次测量,和一张按瓦数画的分流图。
· 4 min read
pmset -g log 在我这台 Mac 上,一次输出23.9 MB。
MenuCue v0.5.0 的发布说明里,Power 页写着睡眠和唤醒的诊断,有唤醒历史。差不多两个小时后的一个提交说明里写着,这个列表在这台 Mac 上其实一直是空的。读取有个16 MB 的上限,23.9 比16大,命令被掐掉,界面上留下的是一句英文报错,大意是返回的数据太多。
空列表
那23.9 MB 里,98.6%是一个叫 Assertions 的段落,这次调用根本不读它。要的那一点东西,混在十万多行里。
改法是边读边筛:管道里的数据一路读过去,只留符合条件的行。最后23.9 MB 里留下了260 KB,后面要处理的只有这260 KB。
先量一下
筛是筛了,一开始很慢。提交说明里的端到端数字,是从36.5秒到12.0秒,其中5.4秒是 pmset 自己在吐数据。
慢的地方有两处,都在应用这一边。一处是拆行:每拆一行就从缓冲区前面删掉一段,24 MB 拆下来成了平方级。另一处是过滤函数收的是 String,为了丢掉98.6%的行,先给105,000行每一行造一个 String,后来改成了按字节过滤。
最后是12.0秒。我觉得这组数字最有用的地方,是告诉我哪一块还能动,哪一块碰不了,那5.4秒就碰不了。
同一个提交里还修了一处更难看的。匹配唤醒的正则没锚住,pmset 的列是补了空格对齐的,「Wake」把「Wake Requests」那一段也吃了进来。那一段是睡下去的时候写的,记的是将来打算醒的时间。结果列表里大约30%是还没发生的唤醒,被当成发生过的,还算进了每天的次数。
18 比 60
不到十分钟,下一个提交又去碰了那一段。
之前的唤醒列表只能显示硬件中断的名字,一串 smc.sysState.Wake 开头的东西。真正安排这次唤醒的进程,其实一直在同一份输出里,就在刚被剔掉的 Wake Requests 里,解析器把它丢了。同一段日志,先从「发生过的唤醒」里剔出去,不到十分钟又拿来当线索。
规矩定得很保守。请求里只有标了星号的那条算候选,因为只有它会最先触发。唤醒时间和请求时间差在90秒以内才算对上,对不上,就写系统记录里的中断名,不去猜离得最近的是哪个进程。最近60次唤醒里,能说出名字的有18次,剩下的42次就老老实实显示原因。
又过了二十个小时左右,电池卡片上加了预估续航,也是这个思路。取系统自己给的数,和按电量百分比除以掉电速度算出来的数,两个里小的那个,再打九折。充电时不显示,超过24小时也不显示,因为那种数是空闲时的噪声外推出来的,不叫续航。代码注释给的理由是这两个数都偏乐观。
一条河
差不多同时,电池卡片上还加了一张分流图,照着 AlDente 里那种画法。插着电的时候,电从插头那头出来分成两股,一股进电池,一股进系统,像一条河分了叉。电池来帮忙的时候反过来,两股汇成一股。
第一版里,插头、电池、系统那几个方块的高度,和飘带的粗细都跟瓦数挂钩,各设了个下限,免得小的那个放不下图标。一个小时之后的提交,标题的意思是让飘带按瓦数成比例,让微光看得见。也就是说第一版不成比例。
改完的样子是:一条飘带从头到尾一个粗细,粗细就是读数。方块不再跟着瓦数变,大小固定,各自居中在自己那股水流上,飘带比方块粗也没关系。微光的周期从6秒改成了3秒。
最细的那一股还是有个下限,11个点(point,不是像素),再细标签就放不下了。所以整张图也不是完全按比例的,最细的那一股是例外。
Copyright
© 2021-present TalexDS. All rights reserved.
Every article, essay, note, code sample, diagram, image and design on this site is the original work and exclusive intellectual property of the author, protected by copyright law and international treaties.
No reproduction. Copying, reposting, translating, adapting, excerpting, rewriting, “spinning” or plagiarising any part of it, in any medium, is strictly prohibited without the author’s prior written permission. Commercial use of any kind is forbidden.
No AI. No crawling. Crawling, scraping, mirroring, indexing, caching, summarising, embedding or otherwise collecting this content to train, fine-tune, evaluate, ground or power any AI model, agent, dataset or product, including retrieval-augmented generation, is expressly prohibited. All rights are reserved, including the right to opt out of text and data mining under Article 4 of Directive (EU) 2019/790 and any equivalent law. AI crawlers and agents must not access or process this page.
Violations will be pursued. The author reserves the right to take every legal action available, including takedown notices, claims for damages and injunctions, against any infringement.
版权声明:本站全部文章、笔记、代码示例、图片与设计均为作者原创,受《中华人民共和国著作权法》及国际公约保护。未经作者书面许可,严禁任何形式的转载、搬运、改写、洗稿与抄袭,严禁商业使用。严禁 AI 爬取:禁止以训练、微调、评测、检索增强或任何其他目的,抓取、镜像、索引、缓存、摘要或向量化本站内容。一经发现,将依法追究法律责任。
Distributed on an “AS IS” basis without warranties.