Since I got my MacBook with the M1 chip, it always runs out of battery in a week if left unused. Last night, after charging it fully, I observed that it consumed 10% of battery overnight while in sleep mode with the lid closed.
TL;DR: Execute
sudo pmset -b powernap 0
to turn off Power Nap, and it won't lose even 1% overnight with the lid closed.
The Disappearing Power Nap#
In the battery settings of the MacBook (called "Energy Saver" on desktops), there are always two switches:
- Wake for network access
- Enable Power Nap
The specific meanings of these can be found in the official support, simply put:
- Wake for network access: Allows the computer to wake up to provide services when it is accessed. For example, sharing printers or files. It will also periodically wake up to broadcast file update notifications (if file sharing is enabled). Note that this option does not mean "wake up to allow the local programs to update over the network."
- Power Nap: Allows waking up during sleep to update its own data, such as emails, iCloud synchronization, and Time Machine.
So the functions of these two options should be clear. In the system settings of macOS 12, there was a clear explanation for "Power Nap." However, macOS 13 added an explanation for "Wake for network access," which is very confusing, and devices with the M1 chip no longer display the switch for "Power Nap."
From the image above, it can be seen that the explanation for "Wake for network access" in macOS 13 is very similar to Power Nap, giving the illusion that these two options are merged. Based on this explanation, it can be understood that turning off network wake will prevent background data updates. However, the fact is that regardless of whether "network wake" is turned on or off, "Power Nap" is always on, and background updates always occur during sleep, which is the culprit for battery drain during sleep.
It feels like Apple is being quite clever; they are too proud of the power consumption of ARM chips and presumptuously have default background updates enabled. To avoid causing trouble for users, they even modified the description of another option to make it seem like it can be turned off. There are numerous complaints online about the standby power consumption of M1 devices, and various analyses have not completely resolved the issue.
pmset Power Management#
pmset
(Power Management Set) is a command-line power management tool for macOS, and the related options in system settings are what it aims to manage, but pmset
provides more detailed configurations.
How do I determine that "network wake" and "Power Nap" are not merged? In
pmset
, "network wake" is managed bywomp
, while "Power Nap" is associated withpowernap
.
Note that different devices support different configuration parameters, and many parameters such as standbydelaylow/high
are ineffective on M1 devices. This is likely due to Apple's confidence, leading to the removal of these detailed power-saving strategies.
Configuration Query#
Note the distinction:
- Sleep: Keeps memory powered
- Standby: Memory data is written to disk, and memory is powered off
- Hibernate: Standby mode. Emphasizes the action of entering standby (e.g., closing the lid), whether it is sleep or standby depends on the settings.
Query the currently effective configuration:
Query user configuration:
Some processes may prevent standby, and these will be reflected in the currently effective configuration, so they may not necessarily match the user configuration.
Here is a comparison table:
Attribute | Unit | Remarks | System Settings (macOS 13) |
---|---|---|---|
standby/autopoweroff* | 0/1 | Allows switching from sleep to standby | |
powernap | 0/1 | Power Nap | Battery - Options - Enable Power Nap |
networkoversleep | 0/1 | How to handle shared networks during sleep. Modification not supported | |
disksleep | minutes | Disk sleep wait time, 0 means off | |
sleep* | minutes | Sleep wait time, 0 means no sleep | |
hibernatemode* | 0/3/25 | Standby mode. 0: Sleep, 25: Standby, 3: Sleep then Standby | |
ttyskeepawake | 0/1 | Do not sleep when there is an active tty (terminal session) | |
displaysleep | minutes | Display sleep wait time | Lock screen - Turn off display when inactive |
tcpkeepalive* | 0/1 | Allow TCP connections | |
lowpowermode | 0/1 | Low power mode | Battery - Low Power Mode |
womp | 0/1 | Allow network wake | Battery - Options - Wake for network access |
gpuswitch | 0/1/2 | 0: Integrated graphics, 1: Dedicated graphics, 2: Automatic | |
standbydelayhigh/low* | seconds | Wait time to switch from sleep to standby | |
highstandbythreshold | 0-100 | If remaining power exceeds this number, standbydelayhigh takes effect, otherwise low takes effect | |
proximitywake | 0/1 | Wake when devices logged into the same account are nearby |
If executing
pmset -g custom
finds that some attributes are missing, it means the current device does not support them.
These attributes cannot be interpreted solely by their literal meanings; many times they are used in conjunction. Here are some common points to note:
- Sleep: Even if the sleep timer conditions are met, it does not necessarily mean it will enter standby; for example, "screen on" will prevent sleep. All conditions must be met for sleep to occur. The default in battery mode for M1 MacBooks is
sleep=1
, meaning the sleep wait time is actually controlled bydisplaysleep
. - Hibernate mode: Whether memory is written to disk is also controlled by
standby
andautopoweroff
.- 0: Only sleep, will not persist data in memory. If power is lost, unsaved data will be lost.
- 25: Only standby. Each time it enters standby, it persists memory and stops powering the memory. Upon reboot, it restores memory from disk. Clearly, waking up will be a bit slower.
- 3: Hybrid mode, first sleep then standby.
- tcpkeepalive: There is a warning when disabling via command line, which may affect core system functions, such as FindMyMac. In practice, enabling it does not have much impact; just turning off
powernap
is sufficient. - standby/autopoweroff: These two currently seem to serve the same function, just in different contexts.
standby
is for extending battery life on MacBooks, whileautopoweroff
is to meet EU energy-saving requirements for desktops, which is why MacBooks do not have this attribute.
Modify Configuration#
Execute
sudo pmset restoredefaults
to restore defaults.
Modifying configurations requires sudo privileges
The command format for modifying configurations is:
pmset [-a | -b | -c | -u] [setting value] [...]
-a
: Effective for all modes-b
: Effective for battery mode-c
: Effective under power adapter-u
: Effective under UPS power
If the output of
pmset -g custom
does not include certain modes, it means the device does not support them.
Here are some commonly used configuration commands:
- Turn off Power Nap under battery (recommended):
sudo pmset -b powernap 0
- Disable TCP connections under battery (may cause some system functions to be unavailable):
sudo pmset -b tcpkeepalive 0
- Force hibernation under battery during standby (persist memory, power off):
sudo pmset -b hibernatemode 25
Wake Analysis#
View the number of sleep/wake cycles since boot:
Output results:
Field | Comment | |
---|---|---|
Sleep Count | Number of sleeps | |
Dark Wake Count | Number of background wakes (screen off) | |
User Wake Count | Number of screen-on wakes (usually user-initiated) |
View detailed background wake records:
pmset -g log | grep -e "Wake from" -e "DarkWake" -e "due to"
It can be quite difficult to understand
AOP.OutboxNotEmpty spu_queue_overflow_ep42
: 1-2 hours once is normal
View standby locks:
Sometimes the system or applications may prevent entering standby; these runtime temporary standby locks are called assertions
, and they will be reflected in the real-time power configuration (pmset -g
), and can also be queried using the above command. The output is as follows:
Assertion status system-wide:
BackgroundTask 0
ApplePushServiceTask 0
UserIsActive 1
PreventUserIdleDisplaySleep 0
PreventSystemSleep 0
ExternalMedia 0
PreventUserIdleSystemSleep 1
NetworkClientActive 0
Listed by owning process:
........
Note that the subsequent array represents whether the corresponding lock is active, not the number of locks. It will show which specific process activated the lock and whether there is a timeout. Usually, UserIsActive
and PreventUserIdleSystemSleep
locks are both active:
- UserIsActive: A system process is determining whether the user is active, with a timeout of 120 seconds
- PreventUserIdleSystemSleep: A system process holds this lock because the screen is on, which will be automatically released after the screen sleeps.