diff --git a/bin/omarchy-update-system-pkgs b/bin/omarchy-update-system-pkgs index ac12a999..564f9548 100755 --- a/bin/omarchy-update-system-pkgs +++ b/bin/omarchy-update-system-pkgs @@ -37,6 +37,7 @@ sudo env OMARCHY_UPDATE_PACMAN=1 pacman -Syu --noconfirm \ --overwrite '/etc/systemd/system/plocate-updatedb.service.d/ac-only.conf' \ --overwrite '/etc/systemd/system.conf.d/20-omarchy-nofile.conf' \ --overwrite '/etc/systemd/user.conf.d/20-omarchy-nofile.conf' \ + --overwrite '/etc/systemd/zram-generator.conf' \ --overwrite '/usr/lib/systemd/system-sleep/unmount-fuse' \ --overwrite '/usr/share/plymouth/themes/omarchy/*' \ --overwrite '/usr/share/sddm/hyprland.lua' \ diff --git a/bin/omarchy-upgrade-to-quattro b/bin/omarchy-upgrade-to-quattro index 46741bb4..22412897 100755 --- a/bin/omarchy-upgrade-to-quattro +++ b/bin/omarchy-upgrade-to-quattro @@ -1087,6 +1087,7 @@ run_final_system_package_upgrade() { --overwrite '/etc/systemd/system/plocate-updatedb.service.d/ac-only.conf' \ --overwrite '/etc/systemd/system.conf.d/20-omarchy-nofile.conf' \ --overwrite '/etc/systemd/user.conf.d/20-omarchy-nofile.conf' \ + --overwrite '/etc/systemd/zram-generator.conf' \ --overwrite '/usr/lib/systemd/system-sleep/unmount-fuse' \ --overwrite '/usr/share/plymouth/themes/omarchy/*' \ --overwrite '/usr/share/sddm/hyprland.lua' \ diff --git a/etc/sysctl.d/99-omarchy-sysctl.conf b/etc/sysctl.d/99-omarchy-sysctl.conf index b8845467..d5ae09ea 100644 --- a/etc/sysctl.d/99-omarchy-sysctl.conf +++ b/etc/sysctl.d/99-omarchy-sysctl.conf @@ -1,2 +1,23 @@ # Solve common flakiness with SSH (MTU discovery on flaky links). net.ipv4.tcp_mtu_probing=1 + +# Tune reclaim for swap on zram, which is orders of magnitude faster than the +# disk swapfile these defaults assume. + +# Anything above 100 tells the kernel that evicting an anonymous page is +# cheaper than dropping a page-cache page it would have to re-read from disk. +# With a compressed RAM device that is true, so the disk-era default of 60 +# leaves the page cache starved. +vm.swappiness=180 + +# Read one page per swap-in fault. The default of 8 pays for a seek that zram +# doesn't have, and every extra page costs a separate decompression. +vm.page-cluster=0 + +# Don't let external fragmentation raise the watermarks, which produces +# reclaim bursts while memory is still free. +vm.watermark_boost_factor=0 + +# Keep ~1.25% of memory free instead of 0.1%, so kswapd reclaims in the +# background rather than letting allocations stall in direct reclaim. +vm.watermark_scale_factor=125 diff --git a/etc/systemd/zram-generator.conf b/etc/systemd/zram-generator.conf new file mode 100644 index 00000000..d794ad16 --- /dev/null +++ b/etc/systemd/zram-generator.conf @@ -0,0 +1,12 @@ +# Compressed swap in RAM. zstd averages around 3:1, so the worst case for a +# full device is roughly a third of the size below. +# +# The generator's own default caps this at 4G, which sends machines with a lot +# of memory to the disk swapfile far earlier than they need to go. +[zram0] +zram-size = min(ram / 2, 8192) +compression-algorithm = zstd + +# Above the pri=0 that omarchy-hibernation-setup gives the disk swapfile, so +# zram absorbs everything until it's full. +swap-priority = 100 diff --git a/migrations/1784961000.sh b/migrations/1784961000.sh new file mode 100644 index 00000000..75b631da --- /dev/null +++ b/migrations/1784961000.sh @@ -0,0 +1,24 @@ +echo "Tune reclaim for swap on zram" + +# Everything here only applies the shipped config early; boot picks it up +# regardless. Nothing is worth failing the migration chain over, so each step +# falls back to asking for a reboot. + +# Load our file specifically rather than --system, which returns nonzero for +# any invalid key in any admin sysctl file on the machine. +sudo sysctl -p /etc/sysctl.d/99-omarchy-sysctl.conf >/dev/null || true + +if sudo systemctl daemon-reload; then + # Resizing swaps the device off first, which faults every stored page back + # into memory. That's only cheap while it's empty, so a device under + # pressure keeps its old size until the next boot. A device that doesn't + # exist yet reads as empty, which is what we want: the restart brings it up + # against the unit daemon-reload just generated. + zram_used=$(awk '$1 == "/dev/zram0" {print $4}' /proc/swaps) + + if [[ ${zram_used:-0} == 0 ]] && sudo systemctl restart dev-zram0.swap; then + exit 0 + fi +fi + +omarchy-state set reboot-required