banner
 Sayyiku

Sayyiku

Chaos is a ladder
telegram
twitter

pmset 电源管理让 Macbook Pro乖乖小憩

自从 M1 芯片的 macbook 买到手,搁着不用总是一周就没电了。昨晚充满观察了一下,一夜合盖休眠竟然消耗了 10% 的电。

TL;DR: 执行 sudo pmset -b powernap 0 关掉小憩,一晚上合盖 1% 都没掉。

消失的小憩#

在 MacBook 的电池设置(台式机叫「节能」)里一直有两个开关:

  • 唤醒以供网络访问
  • 启用电能小憩

这俩的具体含义在官方支持上可以找到,简单来说:

  • 唤醒以供网络访问:当电脑被访问时允许唤醒以提供服务。比如向外共享打印机或文件。同时也会定期唤醒来广播文件更新通知(如果启用了文件共享的话)。注意,这个选项的意思不是「唤醒来让本机的程序可以联网更新」。
  • 小憩:睡眠时允许唤醒来更新自身的数据,例如邮件、iCloud 同步以及时间机器。

那么这两个选项各自的作用应该可以整明白了。在 macOS 12 的系统设置里,只对「小憩」做了解释,还算清晰。可是 macOS 13 增加了对「唤醒以供网络访问」的解释,用词非常迷惑,并且 m1 芯片的设备不再显示「小憩」的开关

image

从上图可以看出,macOS 13 中对「唤醒以供网络访问」的解释非常类似小憩,给人一种这两个选项合并的假象。根据这个解释,可以理解为:关掉网络唤醒,就不会在后台更新数据了。然而事实是,无论关不关「网络唤醒」,「小憩」始终是打开的,休眠时始终进行后台更新,这就是休眠耗电的元凶了。

感觉苹果好心机啊,对 arm 芯片功耗太过骄傲,自以为是地默认开启后台更新。为了不让用户找麻烦,还修改了另一个选项的描述让你感觉可以关闭。看到网上有大量 m1 设备待机耗电的抱怨,各种分析最后也没彻底解决。

pmset 电源管理#

pmset (Power Management Set) 是一个 macOS 的命令行电源管理工具,系统设置里的相关选项与它想管理,不过 pmset 提供了更详细的配置。

我怎么认定「网络唤醒」与「小憩」没有合并的呢?在 pmset 中,「网络唤醒」管理的是 womp,「小憩」关联的是 powernap

注意,不同设备所支持的配置参数不同,很多参数比如 standbydelaylow/high 在 m1 设备上无效。大概还是因为苹果的自信,就去掉这些细节的节电策略了。

配置查询#

注意区分:

  • 睡眠 sleep:保持内存供电
  • 休眠 standby:内存数据写入硬盘,内存断电
  • hibernate:待机模式。强调的是进入待机这一操作(比如关闭盖子),具体是睡眠还是休眠要看设置。

查询当前生效的配置:

查询用户配置:

因为一些进程可能会阻止待机,这些会反映在当前生效的配置中,所以不一定与用户配置相同。

给出一个对照表:

属性单位备注系统设置 (macOS 13)
standby/autopoweroff*0/1允许从睡眠切换到休眠
powernap0/1电源小憩电池 - 选项 - 启用电能小憩
networkoversleep0/1睡眠时如何处理共享网络。不支持修改
disksleep分钟关闭硬盘等待时间,0 为关闭
sleep*分钟睡眠等待时间,0 为不睡眠
hibernatemode*0/3/25待机模式。0: 睡眠,25: 休眠,3: 先睡眠后休眠
ttyskeepawake0/1有活跃的 tty(终端会话)时不休眠
displaysleep分钟关闭显示器等待时间锁定屏幕 - 不活跃时关闭显示器
tcpkeepalive*0/1允许 tcp 连接
lowpowermode0/1省电模式电池 - 低电量模式
womp0/1允许网络唤醒电池 - 选项 - 唤醒以供网络访问
gpuswitch0/1/20: 集成显卡,1: 独立显卡,2: 自动
standbydelayhigh/low*从睡眠切换到休眠的等待时间
highstandbythreshold0-100剩余电量超过这个数 standbydelayhigh 生效,否则 low 生效
proximitywake0/1登录同一帐户的设备靠近时唤醒

如果执行 pmset -g custom 发现缺少一些属性,就是当前设备不支持。

这些属性实际效果不能光看字面意思,很多时候是配合着用的,下面是几个常见的注意事项:

  • sleep: 即使 sleep 计时器条件满足也不见得一定会进入待机,比如「屏幕开启」会阻止睡眠。需要所有条件都满足才可以睡眠。m1 macbook 电池模式下默认 sleep=1,也就是说睡眠等待时间实际上由 displaysleep 控制。
  • hibernatemode:具体是否会把内存写入硬盘还同时受到 standbyautopoweroff 的控制。
    • 0:仅睡眠,不会把持久化内存中的数据。若掉电则丢失未保存的数据。
    • 25:仅休眠。每次待机都持久化内存,并停止内存供电。重启时从硬盘恢复内存。显然唤醒时会慢一点。
    • 3:混合模式,先睡眠再休眠。
  • tcpkeepalive: 通过命令行关闭时有警告,会影响系统核心功能,比如 FindMyMac。实测开启影响不大,只需关闭 powernap 足够了。
  • standby/autopoweroff:这俩目前看作用一样,只是出现的背景不同。standby 是在 macbook 上延长续航,autopoweroff 为了让台式机满足欧盟节能要求,所以 macbook 没有这个属性。

修改配置#

执行 sudo pmset restoredefaults 可恢复默认。

修改配置需要 sudo 权限

修改配置命令格式为:

pmset [-a | -b | -c | -u] [setting value] [...]
  • -a: 对所有模式生效
  • -b: 对电池模式生效
  • -c: 电源适配器下生效
  • -u: UPS 供电下有效

pmset -g custom 的输出没有某些模式,就是设备不支持。

下面给几个常用配置命令:

  • 电池下关闭小憩(推荐)sudo pmset -b powernap 0
  • 电池下禁止 TCP 连接(可能导致部分系统功能不可用): sudo pmset -b tcpkeepalive 0
  • 电池下待机时强制休眠(持久化内存,断电): sudo pmset -b hibernatemode 25

唤醒分析#

查看从开机以来的睡眠 / 唤醒次数:

输出的结果:

字段注释
Sleep Count睡眠次数
Dark Wake Count后台唤醒次数(不亮屏)
User Wake Count亮屏唤醒次数(通常是用户手动唤醒)

查看详细后台唤醒记录:

pmset -g log | grep -e "Wake from" -e "DarkWake" -e "due to"

比较难看懂

  • AOP.OutboxNotEmpty spu_queue_overflow_ep42: 1-2 小时一次是正常的

查看待机锁:

有时系统或应用程序会阻止进入待机,这些运行时的临时待机锁称为 assertions,它们会反映在实时电源配置里 (pmset -g),也可以通过上面命令查询。输出如下:

Assertion status system-wide:
   BackgroundTask                 0
   ApplePushServiceTask           0
   UserIsActive                   1
   PreventUserIdleDisplaySleep    0
   PreventSystemSleep             0
   ExternalMedia                  0
   PreventUserIdleSystemSleep     1
   NetworkClientActive            0
Listed by owning process:
   ........

注意后面的数组代表对应锁是否启动,而不是锁的个数。下面会显示具体哪个进程启动了锁,以及是否有超时时间。通常 UserIsActivePreventUserIdleSystemSleep 这两个锁都是启动的:

  • UserIsActive: 有个系统进程在判断用户是否活跃,超时 120 秒
  • PreventUserIdleSystemSleep: 有个系统进程因为屏幕已点亮而持有这个锁,屏幕休眠后会自动释放的。
加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。