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.
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:
suspendfor deep sleep when you are taking a break during your work stretch and expect to come back to actually work on it.
hibernatefor 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-hibernategives 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!
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.
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:
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.
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
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
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
# 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"
GRUB and reboot:
sudo update-grub sudo reboot
Use your system’s
physical offsets to customize and add the following line to your
initramfs and reboot:
sudo update-initramfs -c -k all sudo reboot
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:
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
suspendand enter your password to put your system in deep sleep mode. After 2 hours, it should automatically enter hibernation mode.
Simply closing the lid will put it in deep sleep mode. It should be possible to update the system to
suspend-then-hibernatewhen closing the lid. But, I haven’t tried it yet.
Disclaimer: Opinions are my own.