From 4b7375c0775b3dacfe55b4dedb5a6bea46fccb19 Mon Sep 17 00:00:00 2001 From: Ryan Yin Date: Sat, 29 Aug 2026 11:16:12 +0800 Subject: [PATCH] fix(nixos): gate zram kernel sysctl tunings behind modules.zram.enable The zram module was auto-imported on all hosts via base scanPaths, and its swappiness=180/page-cluster=0 tunings leaked onto hosts that disabled zram (e.g. idols-ai with a disk swapfile, pushing cold anon pages to disk swap). Wrap the whole module in modules.zram.enable (default true); idols-ai now turns off zram and its tunings with a single switch. --- hosts/idols-ai/default.nix | 3 +- modules/nixos/base/zram.nix | 98 +++++++++++++++++++++++-------------- 2 files changed, 63 insertions(+), 38 deletions(-) diff --git a/hosts/idols-ai/default.nix b/hosts/idols-ai/default.nix index 81fac102..2b88e94a 100644 --- a/hosts/idols-ai/default.nix +++ b/hosts/idols-ai/default.nix @@ -39,7 +39,8 @@ in ]; # Zram consumes physical memory for compression, which can cause a deadlock and system hang if the model size approaches the physical memory limit. - zramSwap.enable = lib.mkForce false; + # Disable the whole module (zram device + its swappiness=180 sysctl tunings); this host uses a disk swapfile instead. + modules.zram.enable = false; services.sunshine.enable = false; services.tuned.ppdSettings.main.default = lib.mkForce "performance"; diff --git a/modules/nixos/base/zram.nix b/modules/nixos/base/zram.nix index 80ce1648..1ee4b6e9 100644 --- a/modules/nixos/base/zram.nix +++ b/modules/nixos/base/zram.nix @@ -1,44 +1,68 @@ -{ lib, ... }: { - # Enable in-memory compressed devices and swap space provided by the zram kernel module. - # By enable this, we can store more data in memory instead of fallback to disk-based swap devices directly, - # and thus improve I/O performance when we have a lot of memory. - # - # https://www.kernel.org/doc/Documentation/blockdev/zram.txt - zramSwap = { - enable = true; - # one of "lzo", "lz4", "zstd" - algorithm = lib.mkDefault "zstd"; - # Priority of the zram swap devices. - # It should be a number higher than the priority of your disk-based swap devices - # (so that the system will fill the zram swap devices before falling back to disk swap). - priority = lib.mkDefault 100; - # Maximum total amount of memory that can be stored in the zram swap devices (as a percentage of your total memory). - # Defaults to 1/2 of your total RAM. Run zramctl to check how good memory is compressed. - # This doesn’t define how much memory will be used by the zram swap devices. - memoryPercent = lib.mkDefault 50; - }; + lib, + config, + ... +}: +let + cfg = config.modules.zram; +in +{ + options.modules.zram.enable = + lib.mkEnableOption '' + zram in-memory swap device plus kernel sysctl tunings for it. - # Optimizing swap on zram - boot.kernel.sysctl = { - # vm.swappiness - Controls kernel preference for swapping (range: 0-200, default: 60) - # For in-memory swap devices like zram/zswap, values above 100 are recommended. - "vm.swappiness" = lib.mkDefault 180; + The sysctl tunings (swappiness=180 etc.) are designed for in-memory swap + devices only; they are gated behind this switch so that hosts which + disable zram (e.g. using a disk swapfile instead) also revert to the + kernel default swappiness instead of leaking zram tunings onto disk swap. - # vm.watermark_boost_factor - Controls aggressiveness of memory reclaim (default: 15000) - # Setting to 0 disables watermark boost, preventing premature memory reclamation. - # This allows fuller memory utilization before the kernel starts reclaiming pages. - "vm.watermark_boost_factor" = lib.mkDefault 0; + Enabled by default; hosts that want disk-only swap should set it to false. + '' + // { + default = true; + }; - # vm.watermark_scale_factor - Controls kswapd wakeup frequency (range: 1-1000, default: 10) - # A higher value triggers background memory reclamation earlier (at 12.5% memory pressure). - # Value 125 means kswapd becomes active when free memory drops below 1/125 of total memory, - # balancing memory more proactively to prevent sudden swap storms at high swappiness values. - "vm.watermark_scale_factor" = lib.mkDefault 125; + config = lib.mkIf cfg.enable { + # Enable in-memory compressed devices and swap space provided by the zram kernel module. + # By enable this, we can store more data in memory instead of fallback to disk-based swap devices directly, + # and thus improve I/O performance when we have a lot of memory. + # + # https://www.kernel.org/doc/Documentation/blockdev/zram.txt + zramSwap = { + enable = true; + # one of "lzo", "lz4", "zstd" + algorithm = lib.mkDefault "zstd"; + # Priority of the zram swap devices. + # It should be a number higher than the priority of your disk-based swap devices + # (so that the system will fill the zram swap devices before falling back to disk swap). + priority = lib.mkDefault 100; + # Maximum total amount of memory that can be stored in the zram swap devices (as a percentage of your total memory). + # Defaults to 1/2 of your total RAM. Run zramctl to check how good memory is compressed. + # This doesn't define how much memory will be used by the zram swap devices. + memoryPercent = lib.mkDefault 50; + }; - # vm.page-cluster - Controls swap readahead (range: 0-6, default: 3) - # 0 means read only 1 page (2^0) at a time, disabling readahead. - # For low-latency devices like zram, readahead hurts performance by fetching unnecessary data. - "vm.page-cluster" = lib.mkDefault 0; + # Optimizing swap on zram + boot.kernel.sysctl = { + # vm.swappiness - Controls kernel preference for swapping (range: 0-200, default: 60) + # For in-memory swap devices like zram/zswap, values above 100 are recommended. + "vm.swappiness" = lib.mkDefault 180; + + # vm.watermark_boost_factor - Controls aggressiveness of memory reclaim (default: 15000) + # Setting to 0 disables watermark boost, preventing premature memory reclamation. + # This allows fuller memory utilization before the kernel starts reclaiming. + "vm.watermark_boost_factor" = lib.mkDefault 0; + + # vm.watermark_scale_factor - Controls kswapd wakeup frequency (range: 1-1000, default: 10) + # A higher value triggers background memory reclamation earlier (at 12.5% memory pressure). + # Value 125 means kswapd becomes active when free memory drops below 1/125 of total memory, + # balancing memory more proactively to prevent sudden swap storms at high swappiness values. + "vm.watermark_scale_factor" = lib.mkDefault 125; + + # vm.page-cluster - Controls swap readahead (range: 0-6, default: 3) + # 0 means read only 1 page (2^0) at a time, disabling readahead. + # For low-latency devices like zram, readahead hurts performance by fetching unnecessary data. + "vm.page-cluster" = lib.mkDefault 0; + }; }; }