The Framework Laptop with Ubuntu 21.10 is a great combination for development. However, the battery drains very quickly during sleep with the vanilla installation. A solution that works great is to enable deep sleep and hibernate. My system can now hibernate for weeks without depleting the battery. Because fine tuning a Linux system is not effortless, I hope this guide make it easier and straighforward to configure and give it a try.
Drain speed
The vanilla installation is configured with light sleep. It sleeps and wakes up very quickly. But, my battery was completely depleted in less that 24 hours of sleep. After enabling deep sleep, it was able to sleep just under 48 hours before depleting the battery completely. Not great.
After configuring hibernate I noticed that it drain just about 2% in 3 days of hibernation. If power loss is linear, then it can go for weeks before depleting completely. Back-of-the-envelope calculation estimates 20% in a month. Not too shabby! Obviously, real world usage would normally include a few breaks when the computer goes to deep sleep and hibernation. As a matter of fact, Linux systemctl
allows you to:
suspend
for deep sleep when you are taking a break during your work stretch and expect to come back to actually work on it.hibernate
for when you are done for the day or the week. Or, when you are going on vacation and taking an extended break from your computer. Or, when you are traveling and about to jump on an airplane.suspend-then-hibernate
gives you the best of two worlds. The system enters deep sleep for 2 hours (default config compiled into the kernel and configurable if you want to recompile it) and then enters hibernation automatically if sleep is uninterrupted. I don’t know for a fact, but this is likely what the macOS kernel is doing to preserve battery life during sleep.
Wake up speed
Waking up from deep sleep takes a couple of seconds if not faster. Waking from hibernation takes about 8 seconds in my system. Whether this is acceptable or too slow is likely a matter of personal opinion and debate. Pragmatically speaking though, it is not an issue and it’s fast enough. And, if my Framework can sleep for weeks when not in use without depleting the battery completely, even better!
Hibernate
How does hibernate work? In simple terms, the system takes a snapshot of your entire RAM and saves it to a swap file on disk. The file has to be large enough to fit your entire RAM. Then, when the system “wakes up”, it actually boots restoring the state by copying the entire contents of the swapfile to RAM. And voila!
Configuring deep sleep and hibernate is straightforward. It boils down to updating one line in your GRUB and initramfs configurations with the right sleep parameter, the disk UUID and swap file offset for saving and restoring the system state when entering and waking up from hibernation.
Configuration
This is how I did it. I consolidated information from some sources cited below to simplify and streamline the process. Be careful when making changes. While it’s straightforward, typos and mistakes could render your system unusable or make it difficult to restore.
It all boils down to ensuring that you have a swap file large enough for your RAM and adding the following parameters to GRUB_CMDLINE_LINUX_DEFAULT
in your /etc/default/grub
configuration file:
mem_sleep_default=deep
resume=UUID=012345ab-00a0-000a-a000-00aa000aa0a0
resume_offset=123456789
The disk UUID and offset are placeholders. You’ll make a note of the ones for your system running some commands below.
1. Resize swap file
Resize the swapfile. My system has 32 GB of RAM. I configured the swap file with 34 GB just to be safe. My disk has 1 TB so space is not an issue. Adjust according to your system.
sudo swapoff /swapfile
sudo rm /swapfile
sudo dd if=/dev/zero of=/swapfile bs=1M count=34816
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
2. Get UUID and offset
Get UUID of the disk containing the swap file. My system has only one disk. If you have more than one, make sure it’s the one where the swap file resides. Take note of the UUID. You’ll use it later.
blkid
Get physical offset of the swapfile. The number you are looking for is fourth column from the left in the row for ext: 0
under physical_offset:
. Take note of this value. You’ll use it later.
sudo filefrag -v /swapfile
For example, in my system it is 136611840
:
Filesystem type is: ef53
File size of /swapfile is 35651584000 (8704000 blocks of 4096 bytes)
ext: logical_offset: physical_offset: length: expected: flags:
0: 0.. 227327: 136611840.. 136839167: 227328:
...
3. Update GRUB
Use the UUID
and physical offsets
to enable deep sleep and resume location from hibernate during boot time. Add the following lines to your /etc/default/grub
configuration file. This way, you can easily choose which method to use. Use the values from your system to customize line 1.
below. Note that there are no quotes around the UUID
:
# 1. Deep sleep + resume from hibernate to /swapfile: Drains more normally.
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash mem_sleep_default=deep resume=UUID=012345ab-00a0-000a-a000-00aa000aa0a0 resume_offset=123456789"
# 2. Deep sleep: Wakes up fast but drains fast.
#GRUB_CMDLINE_LINUX_DEFAULT="quiet splash mem_sleep_default=deep"
# 3. Light sleep: Wakes up fast but drains very fast.
#GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"
Update GRUB
and reboot:
sudo update-grub
sudo reboot
4. Update initramfs
Use your system’s UUID
and physical offsets
to customize and add the following line to your /etc/initramfs-tools/conf.d/resume
file:
resume=UUID=012345ab-00a0-000a-a000-00aa000aa0a0 resume_offset=123456789
Update initramfs
and reboot:
sudo update-initramfs -c -k all
sudo reboot
5. Aliases
I couldn’t figure out yet how to put a Hibernate option in the Power off/Logout Menu. But, since I always have a terminal open, I created two handy shortcuts:
alias hibernate='echo "Hibernate" && sudo systemctl hibernate'
alias suspend='echo "Suspend then Hibernate" && sudo systemctl suspend-then-hibernate'
6. Verify and enjoy!
You now have options:
Hibernate
At this point, you should be able to run
hibernate
, enter your password and put the computer in hibernation mode. Leave all your windows and work open to verify that it restores the state exactly as you left it. To wake up, press the power button. It will take a few seconds to wake up. When you unlock the screen, you should get your entire session restored exactly as it was before.Suspend then Hibernate
Run
suspend
and enter your password to put your system in deep sleep mode. After 2 hours, it should automatically enter hibernation mode.Deep sleep
Simply closing the lid will put it in deep sleep mode. It should be possible to update the system to
suspend-then-hibernate
when closing the lid. But, I haven’t tried it yet.
References
Disclaimer: Opinions are my own.