The case of MacBook battery draining

Recently I discovered that my MacBook Pro battery drains completely overnight. This started sometime after upgrading to macOS Catalina.

The TL;DR version is – disable TCP keepalive while asleep.
For the full details – read on.

I looked at the available power saving settings in the UI but did not find anything that would explain it. The Activity Monitor also did not provide any obvious clues.

This was a bit disappointing as the machine is a 2018 15″ MacBook, therefore I expected to the battery life to be really good.

There are plenty of threads on the internet with similar complaints, but they mostly suggest disabling things left and right, without really explaining why that should help.

And what puzzled (and still does) me the most was that how come it used to work just fine before, what is triggering it now?

Turns out that you can see the wake events in the logs by doing something similar to

log show --style syslog --last 300m | fgrep "Wake reason"

On my machine I saw bunch of lines like:

2020-01-03 07:44:33.103996+0200  localhost kernel[0]: (AppleTopCaseHIDEventDriver) [HID] [ATC] AppleDeviceManagementHIDEventService::processWakeReason Wake reason: Host (0x01)
2020-01-03 07:44:33.825185+0200  localhost kernel[0]: (AppleTopCaseHIDEventDriver) [HID] [ATC] AppleDeviceManagementHIDEventService::processWakeReason Wake reason: Host (0x01)
2020-01-03 07:45:26.413995+0200  localhost kernel[0]: (AppleACPIPlatform) AppleACPIPlatformPower Wake reason: EC.ARPT (Maintenance)
2020-01-03 07:45:26.413998+0200  localhost kernel[0]: (AppleACPIPlatform) AppleACPIPlatformPower Wake reason: EC.ARPT (Maintenance)
2020-01-03 07:45:51.486356+0200  localhost corespeechd[528]: [com.apple.corespeech:Framework] -[CSHostDaemonMac _isWakeReasonVoiceTrigger] Wake reason: <private>
2020-01-03 07:45:51.486367+0200  localhost corespeechd[528]: [com.apple.corespeech:Framework] -[CSHostDaemonMac _getPowerAssertionIfWakenByVoiceTriggerNotFromS3Sleep] Wake reason is not VoiceTrigger or it woke from S3

Note the reason – Wake reason: EC.ARPT

More googling told me that this means – Airport, which means something with wifi. OK, so the machine is waking up to do something with the network? Interesting.

Another useful command I discovered was pmset, which had especially useful argument to show logs – pmset -g log
This one also showed that waking happens because of network:

2020-01-03 08:50:27 +0200 Assertions          	PID 246(mDNSResponder) Created MaintenanceWake "mDNSResponder:maintenance" 00:00:00  id:0x0xd0000a385 [System: No Assertions]
2020-01-03 08:50:27 +0200 Assertions          	PID 246(mDNSResponder) Released MaintenanceWake "mDNSResponder:maintenance" 00:00:00  id:0x0xd0000a385 [System: No Assertions]
2020-01-03 08:50:29 +0200 Assertions          	PID 125(powerd) Created InternalPreventSleep "PM configd - Wait for Device enumeration" 00:00:00  id:0x0xd0000a387 [System: No Assertions]
2020-01-03 08:50:29 +0200 DarkWake            	DarkWake from Normal Sleep [CDN] : due to EC.ARPT/Maintenance Using BATT (Charge:96%) 45 secs
2020-01-03 08:50:29 +0200 WakeDetails         	DriverReason:WLC_E_TKO - DriverDetails:
2020-01-03 08:50:29 +0200 HibernateStats      	hibmode=3 standbydelaylow=10800 standbydelayhigh=86400                     	          6382
2020-01-03 08:50:29 +0200 WakeTime            	WakeTime: 2.367 sec

OK, the pmset command also has quite useful manpage.
After seeing the output of pmset -g, where it lists all the settings that are related to sleeping I was wondering what tcpkeepalive has to do with sleeping. Why yes, I have noticed that whenever I open my macbook, the wifi works instantly and my SSH sessions are all still active, but I never put too much thought to the fact that in order for this all to work, of course a TCP keepalive is periodically sent out.

OK, so I disable tcpkeepalive while sleeping with:

sudo pmset -b tcpkeepalive 0

And the problem disappeared.
How anticlimactic.

Now, of course, I cannot benefit from all the nice features that the keepalive was providing me and I still don’t understand what changed, why this always worked and now it does not?

However what disappoints me the most is that this is a problem for many users (lots of posts on forums), and Apple is just pretending not to see it.
I mean. It should “just work”. Why do I need to mess with my power settings on my 3K+ laptop?

If only I would not be invested into the Apple ecosystem…