Skip to content

Commit

Permalink
feat: auto-configure zram at boot with optimal settings
Browse files Browse the repository at this point in the history
  • Loading branch information
mmstick authored Dec 28, 2022
1 parent 0b84561 commit 7fcad35
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 7 deletions.
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
debian/
!debian/*.install
!debian/*.links
!debian/*.postinst
!debian/*.postrm
!debian/*.prerm
!debian/*.service
!debian/changelog
!debian/compat
!debian/copyright
!debian/rules
!debian/source/

etc/pop-os/issue
etc/pop-os/issue.net
etc/pop-os/lsb-release
Expand Down
7 changes: 7 additions & 0 deletions debian/control
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ Depends: ${misc:Depends},
python3-repolib (>> 1.3.9),
ubuntu-minimal,
ubuntu-standard,
Recommends: pop-default-settings-zram
Conflicts: pipewire-media-session
Description: default settings for Pop OS
This package contains the default settings used by Pop.

Package: pop-default-settings-zram
Architecture: all
Depends: ${misc:Depends}, pop-default-settings, util-linux
Description: default settings for ZRAM on Pop OS
This package contains the default zram settings used by Pop.
2 changes: 2 additions & 0 deletions debian/pop-default-settings-zram.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
etc/default/pop-zram
usr/bin/pop-zram-config
9 changes: 9 additions & 0 deletions debian/pop-default-settings-zram.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
Description=Auto-configure and enable zram on Pop

[Service]
Type=oneshot
ExecStart=/usr/bin/pop-zram-config

[Install]
WantedBy=multi-user.target
File renamed without changes.
50 changes: 47 additions & 3 deletions debian/pop-default-settings.install
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
etc
lib
usr
etc/apt/apt.conf.d/76pop-default-settings
etc/apt/preferences.d/pop-default-settings
etc/chrony/conf.d/10-system76-nts.conf
etc/chrony/sources.d/system76-nts.sources
etc/modules-load.d/pop-modules.conf
etc/pop-os/flatpak/flathub.flatpakrepo
etc/pop-os/gdm3/custom.conf
etc/pop-os/issue
etc/pop-os/issue.net
etc/pop-os/legal
etc/pop-os/lsb-release
etc/pop-os/os-release
etc/pop-os/update-motd.d/10-help-text
etc/pop-os/update-motd.d/50-motd-news
etc/profile.d/pop-im-ibus.sh
etc/sysctl.d/10-pop-default-settings.conf
etc/update-manager/release-upgrades.d/pop-default-settings.cfg
etc/xdg/autostart/pop-app-folders.desktop
etc/xdg/autostart/pop-flatpak-repos.desktop
lib/systemd/system-sleep/pop-default-settings_bluetooth-suspend
lib/udev/rules.d/60-block-pop.rules
usr/bin/pop-app-folders
usr/bin/pop-cosmic-favorites
usr/bin/pop-flatpak-repos
usr/lib/firefox/browser/defaults/preferences/pop-default-settings.js
usr/lib/firefox/defaults/pref/pop-default-settings.js
usr/lib/systemd/journald.conf.d/pop.conf
usr/share/applications/pop-mimeapps.list
usr/share/gtksourceview-3.0/styles/pop-dark.xml
usr/share/gtksourceview-3.0/styles/pop-light.xml
usr/share/gtksourceview-4/styles/pop-dark.xml
usr/share/gtksourceview-4/styles/pop-light.xml
usr/share/icons/pop-os-branding/256x256/apps/ubuntu-logo-icon.png
usr/share/icons/pop-os-branding/index.theme
usr/share/icons/pop-os-branding/pop_icon.svg
usr/share/icons/pop-os-branding/round-logos/16/distributor-logo.svg
usr/share/icons/pop-os-branding/round-logos/16/ubuntu-logo-icon.svg
usr/share/icons/pop-os-branding/round-logos/22/distributor-logo.svg
usr/share/icons/pop-os-branding/round-logos/24/distributor-logo.svg
usr/share/icons/pop-os-branding/round-logos/32/distributor-logo.svg
usr/share/icons/pop-os-branding/round-logos/48/distributor-logo.svg
usr/share/icons/pop-os-branding/round-logos/64/distributor-logo.svg
usr/share/pipewire/media-session.d/with-alsa
usr/share/pipewire/media-session.d/with-jack
usr/share/pipewire/media-session.d/with-pulseaudio
usr/share/pixmaps/faces/pop-robot.png
usr/share/X11/xorg.conf.d/10-pop-dpms.conf
4 changes: 0 additions & 4 deletions debian/rules
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
#!/usr/bin/make -f

override_dh_installdeb:
dh_installdeb
cp debian/conffiles debian/pop-default-settings/DEBIAN/conffiles

%:
dh $@
8 changes: 8 additions & 0 deletions etc/default/pop-zram
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Default to 16384M as max zram block size.
MAX_SIZE=16384
# Amount of memory to use for zram, from 1 to 200.
PORTION=100
# Default to compress with zstd, which has an average compression ratio of 3.37.
ALGO=zstd
# Higher values encourage the kernel to be more eager to move pages to swap.
SWAPPINESS=180
2 changes: 2 additions & 0 deletions etc/sysctl.d/10-pop-default-settings.conf
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
vm.swappiness = 10
vm.watermark_boost_factor=0
vm.watermark_scale_factor = 125
vm.dirty_bytes = 268435456
vm.dirty_background_bytes = 134217728
67 changes: 67 additions & 0 deletions usr/bin/pop-zram-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#!/bin/bash
# Copyright 2022 System76 <info@system76.com>
# SPDX-License-Identifier: GPL-3.0-only

# If a zram device already exists, ignore
test -b /dev/zram0 && exit 0

ENV_CONF='/etc/pop-zram'

This comment has been minimized.

Copy link
@kwilczynski

kwilczynski Jan 13, 2023

@mmstick, just to double-check: did you meant to use /etc/default/pop-zram path here instead?

This comment has been minimized.

Copy link
@mmstick

mmstick Jan 21, 2023

Author Member

No, /etc/default/pop-zram is an example

This comment has been minimized.

Copy link
@kwilczynski

kwilczynski Jan 21, 2023

@mmstick, got it. Thank you!

I am used to examples on Debian that are customary elsewhere, and the /etc/default serves as a set of configuration files to adjust settings for various system software. Have a look at any other software if you don't want to take my word for it.

An example:

root@rocinante:~# dpkg -S /etc/default
docker-ce, preload, dbus, base-files, amd64-microcode, passwd, console-setup, openvpn, pop-default-settings-zram, avahi-daemon, cryptsetup, chrony, kernelstub, networkd-dispatcher, tailscale, acpi-support, acpid, irqbalance, im-config, ifupdown, cron, haveged, rsync, intel-microcode: /etc/default
root@rocinante:~# dpkg -L tailscale 
/lib
/lib/systemd
/lib/systemd/system
/lib/systemd/system/tailscaled.service
/usr
/usr/bin
/usr/bin/tailscale
/usr/sbin
/usr/sbin/tailscaled
/etc
/etc/default
/etc/default/tailscaled
root@rocinante:~# cat /etc/default/tailscaled
PORT="41641"
FLAGS="-no-logs-no-support"

I adjusted some values there and wondered why none were applied before looking at the script itself. This violated the principle of the least surprise for me.

I created a symbolic link for now. However, it would be nice if installed software packages adhered to commonly established patterns.

This comment has been minimized.

Copy link
@mmstick

mmstick Jan 21, 2023

Author Member

If you use a symbolic link, then it will be overwritten the next time the settings package is updated.

This comment has been minimized.

Copy link
@kwilczynski

kwilczynski Jan 21, 2023

@mmstick, not with a local diversion I have set.


# Load user-defined variabls if a config exists
if test -f ${ENV_CONF}; then
export $(grep -v '^#' ${ENV_CONF} | xargs)
fi

# Default to compress with zstd, which has an average compression ratio of 3.37.
test -n "${ALGO}" || ALGO=zstd

# Max amount of uncompressed RAM that should be compressed.
test -n "${MAX_SIZE}" || MAX_SIZE=16384

# Higher values encourage the kernel to be more eager to move pages to swap.
test -n "${SWAPPINESS}" || SWAPPINESS=180

# Amount of memory to use for zram, from 1 to 200
test -n "${PORTION}" || PORTION=100

if ((PORTION > 200)); then
PORTION=200
elif ((PORTION < 1)); then
PORTION=1
fi

# Number of consecutive pages to read in advance. Higher values increase compression
# for zram devices, but at the cost of significantly reduced IOPS and higher latency.
# It is highly recommended to use 0 for zstd; and 1 for speedier algorithms.
test -n "${PAGE_CLUSTERS}" || PAGE_CLUSTERS=$(test zstd = ${ALGO} && echo 0 || echo 1)

# Total amount of memory accessible to the OS.
TOTAL=$(awk -v p=${PORTION} '/MemTotal/ {printf "%.0f", p * $2 / 102400}' /proc/meminfo)

# Ensure that the size is not greater than the max size.
SIZE=$(((TOTAL > MAX_SIZE)) && echo ${MAX_SIZE} || echo ${TOTAL})

# Load the zram module.
modprobe zram num_devices=1
udevadm settle -t 1

# Create it with our desired size and compression algorithm
zramctl --size "${SIZE}M" --algorithm "${ALGO}" /dev/zram0

# Format it as a swap partition
mkswap /dev/zram0
udevadm settle -t 1

# Activate the zram device with a priority of 1000.
# This device should have a higher priority than disk-based swap.
swapon -p 1000 /dev/zram0

# Apply optimal sysctl values for the zram environment.
sysctl -w "vm.page-cluster=${PAGE_CLUSTERS}" "vm.swappiness=${SWAPPINESS}"

# Ensure at least 1% of total memory is free to avoid system freeze.
MINIMUM=$(awk '/MemTotal/ {printf "%.0f", $2 * 0.01}' /proc/meminfo)
CURRENT=$(sysctl vm.min_free_kbytes | awk '{print $3}')
if ((MINIMUM > CURRENT)); then
sysctl -w "vm.min_free_kbytes=${MINIMUM}"
fi

0 comments on commit 7fcad35

Please sign in to comment.