自從 M1 芯片的 macbook 買到手,搁著不用總是一周就沒電了。昨晚充滿觀察了一下,一夜合蓋休眠竟然消耗了 10% 的電。
TL;DR: 執行
sudo pmset -b powernap 0
關掉小憩,一晚上合蓋 1% 都沒掉。
消失的小憩#
在 MacBook 的電池設置(桌面機叫「節能」)裡一直有兩個開關:
- 喚醒以供網絡訪問
- 啟用電能小憩
這倆的具體含義在官方支持上可以找到,簡單來說:
- 喚醒以供網絡訪問:當電腦被訪問時允許喚醒以提供服務。比如向外共享打印機或文件。同時也會定期喚醒來廣播文件更新通知(如果啟用了文件共享的話)。注意,這個選項的意思不是「喚醒來讓本機的程序可以聯網更新」。
- 小憩:睡眠時允許喚醒來更新自身的數據,例如郵件、iCloud 同步以及時間機器。
那麼這兩個選項各自的作用應該可以整明白了。在 macOS 12 的系統設置裡,只對「小憩」做了解釋,還算清晰。可是 macOS 13 增加了對「喚醒以供網絡訪問」的解釋,用詞非常迷惑,並且 m1 芯片的設備不再顯示「小憩」的開關。
從上圖可以看出,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 | 允許從睡眠切換到休眠 | |
powernap | 0/1 | 電源小憩 | 電池 - 選項 - 啟用電能小憩 |
networkoversleep | 0/1 | 睡眠時如何處理共享網絡。不支持修改 | |
disksleep | 分鐘 | 關閉硬盤等待時間,0 為關閉 | |
sleep* | 分鐘 | 睡眠等待時間,0 為不睡眠 | |
hibernatemode* | 0/3/25 | 待機模式。0: 睡眠,25: 休眠,3: 先睡眠後休眠 | |
ttyskeepawake | 0/1 | 有活躍的 tty(終端會話)時不休眠 | |
displaysleep | 分鐘 | 關閉顯示器等待時間 | 鎖定螢幕 - 不活躍時關閉顯示器 |
tcpkeepalive* | 0/1 | 允許 tcp 連接 | |
lowpowermode | 0/1 | 省電模式 | 電池 - 低電量模式 |
womp | 0/1 | 允許網絡喚醒 | 電池 - 選項 - 喚醒以供網絡訪問 |
gpuswitch | 0/1/2 | 0: 集成顯卡,1: 獨立顯卡,2: 自動 | |
standbydelayhigh/low* | 秒 | 從睡眠切換到休眠的等待時間 | |
highstandbythreshold | 0-100 | 剩餘電量超過這個數 standbydelayhigh 生效,否則 low 生效 | |
proximitywake | 0/1 | 登錄同一帳戶的設備靠近時喚醒 |
如果執行
pmset -g custom
發現缺少一些屬性,就是當前設備不支持。
這些屬性實際效果不能光看字面意思,很多時候是配合著用的,下面是幾個常見的注意事項:
- sleep: 即使 sleep 計時器條件滿足也不見得一定會進入待機,比如「螢幕開啟」會阻止睡眠。需要所有條件都滿足才可以睡眠。m1 macbook 電池模式下默認
sleep=1
,也就是說睡眠等待時間實際上由displaysleep
控制。 - hibernatemode:具體是否會把內存寫入硬盤還同時受到
standby
和autopoweroff
的控制。- 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:
........
注意後面的數組代表對應鎖是否啟動,而不是鎖的個數。下面會顯示具體哪個進程啟動了鎖,以及是否有超時時間。通常 UserIsActive
和 PreventUserIdleSystemSleep
這兩個鎖都是啟動的:
- UserIsActive: 有個系統進程在判斷用戶是否活躍,超時 120 秒
- PreventUserIdleSystemSleep: 有個系統進程因為螢幕已點亮而持有這個鎖,螢幕休眠後會自動釋放的。