Files
debianito-post-install/docs/zram.md
T
stornic56 59c93ba459 nvidia & zram fixes
- Fixed critical NVIDIA driver bug on Debian 13 (Trixie) where repo configuration installed v550 instead of selected v595. Implemented version-specific enabling: cuda-keyring for Trixie, extrepo for Bookworm. Added explicit apt update after repo enable and candidate verification before pinning checks to abort cleanly if expected driver unavailable.
- Rewrote `_install_nvidia_standard()` with auto-detected architecture via `_get_nvidia_arch_family()`. Turing/Ampere/Ada/Blackwell → nvidia-open-kernel-dkms (open module); Maxwell/Pascal/Volta/unknown/empty → nvidia-kernel-dkms (closed, safe fallback). Removed all `nvidia-detect` references across modules and docs.
- Fixed `_install_nvidia_cuda_repo()` to use correct CUDA repository package names: v590/v595 → nvidia-open metapackage (includes nvidia-kernel-open-dkms); v550 and below → nvidia-driver. Added dynamic warning message based on installed module type.
- Fixed uninitialized variable bug in `modules/gaming/tools.sh` causing script abortion under `set -u`. Initialized all local variables (`deb_url`, `sha256`, `json`, `deb_suffix`) with default values and added defensive initialization for `$USER` environment variable.
- Fixed ZRAM configuration persistence bug where old config persisted after changes. Added device reset sequence (swapoff + modprobe -r) before writing new config, post-config verification check, and changed default recommendation from 50% to 25% for systems with >16GB RAM.
- Added `_warn_nvidia_gnome_wayland()` function in `gpu.sh` to warn about Debian bug #1109409 (GDM3 + NVIDIA + Wayland black screen issue). Warning displays only when gdm3 present, GNOME Shell 4.x detected, and NVIDIA driver installed.
- Standardized menu headers across all modules using centralized SCROLL_HINT variable, replacing hardcoded strings with uniform Whiptail instructions. Updated documentation for cuda-keyring (Trixie) and ZRAM configuration flow diagrams.
2026-08-05 21:13:32 -05:00

273 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Option 8: ZRAM Configuration & Memory Optimization
## 1. The Science of ZRAM vs. Traditional Swap
### Core Concept: CPU Cycles vs. Disk I/O
Traditional swap storage operates on a fundamental latency gap that becomes critical under memory pressure:
| Storage Medium | Latency Range | Write Amplification | SSD Wear Impact |
|---------------|---------------|---------------------|-----------------|
| **DRAM (RAM)** | ~1050 nanoseconds | None | Zero |
| **NVMe SSD** | ~2070 microseconds | 1.2x3.0x | Moderate to High |
| **SATA SSD** | ~100200 microseconds | 1.5x4.0x | High |
| **HDD** | ~510 milliseconds | N/A (mechanical) | Irrelevant |
When a Linux system experiences memory pressure, the kernel must decide what to swap out. Traditional swap writes pages directly to disk storage:
- **Time Cost**: Each 4 KiB page write takes microseconds (NVMe) to milliseconds (HDD)
- **Wear Cost**: Every write consumes P/E (Program/Erase) cycles from NAND flash cells, reducing TBW (Terabytes Written) lifespan
- **System Impact**: High latency causes "thrashing" where the system spends more time waiting for disk I/O than executing actual work
### ZRAM's Solution: Compression in RAM
ZRAM creates a compressed block device entirely within physical memory. When pages need to be swapped, they are:
1. **Compressed on-the-fly** using CPU algorithms (LZ4 or ZSTD)
2. **Stored in RAM pool** at compressed size (typically 2:1 to 3:1 ratio)
3. **Decompressed instantly** when needed (microseconds vs milliseconds)
The trade-off is explicit: **CPU cycles for reduced I/O latency**. Modern CPUs can compress/decompress pages in microseconds, making this far cheaper than any disk operation.
### Why Only LZ4 and ZSTD?
The script offers only two algorithms because they represent the optimal balance points:
| Algorithm | Compression Ratio | Speed | CPU Overhead | Best Use Case |
|-----------|------------------|-------|--------------|---------------|
| **LZ4** | ~2:13:1 | Fastest | Lowest | Gaming, real-time workloads |
| **ZSTD** | ~3:15:1 | Medium | Moderate | General use, better memory savings |
- **LZ4**: Prioritizes speed over compression ratio. Ideal for systems where CPU availability is limited or latency-sensitive (gaming servers).
- **ZSTD**: Offers superior compression ratios with acceptable overhead. Best for systems prioritizing maximum effective RAM capacity.
The kernel supports additional algorithms (lzo-rle, deflate, lz4hc), but these are either deprecated, slower, or offer diminishing returns compared to LZ4/ZSTD in modern hardware.
### Extending SSD Lifespan Through Reduced Writes
By intercepting swap writes before they reach physical storage:
- **Write Reduction**: Pages that would write to disk now compress in RAM
- **TBW Conservation**: Each avoided write preserves P/E cycles on NAND flash cells
- **System Longevity**: Critical for systems with limited SSD endurance ratings (e.g., 100 TBW consumer drives)
As the Linux kernel documentation states: *"Users with SSDs as swap devices can extend device lifespan by drastically reducing writes that shorten its life."*
---
## 2. Injection Flow and Configuration Logic (`zram-tools`)
### Pipeline Execution Sequence
The script follows a deterministic flow to ensure safe, reproducible configuration:
```
┌─────────────────────────────────────────────────────────────┐
│ install_zram() Function │
├─────────────────────────────────────────────────────────────┤
│ 1. Validate RAM Detection │
│ └─ Check if RAM_KB is available and non-zero │
│ │
│ 2. Compression Algorithm Selection │
│ ├─ Present menu: LZ4 (fast) vs ZSTD (better ratio) │
│ └─ User choice stored in $algo variable │
│ │
│ 3. Size Calculation Logic │
│ ┌──────────────────────────────────────────────┐ │
│ │ ram_gb > 16 ? 25% : 50% of total RAM │ │
│ │ recommended_mb = ((RAM_KB/1024/1024 + 1) │ │
│ │ / (ram_gb > 16 ? 4 : 2)) │ │
│ └──────────────────────────────────────────────┘ │
│ └─ Result: ~25% RAM if > 16 GB, else ~50% in MB │
│ │
│ 4. Configuration Confirmation │
│ ├─ Display summary with algorithm, size, priority=100 │
│ └─ User must confirm before applying │
│ │
│ 5. Package Installation │
│ sudo apt install -y zram-tools │
│ │
│ 6. Reset Existing ZRAM Device │
│ sudo swapoff /dev/zram0 (ignore errors) │
│ sudo modprobe -r zram (ignore errors) │
│ └─ Guarantees the old device is released before │
│ applying the new configuration │
│ │
│ 7. Configuration File Write │
│ /etc/default/zramswap │
│ ALGO=$algo │
│ SIZE=$zram_size │
│ PRIORITY=100 │
│ │
│ 8. Service Restart │
│ sudo systemctl restart zramswap │
│ └─ Verify: comp_algorithm shows [algo]; sudo zramctl │
└─────────────────────────────────────────────────────────────┘
```
### Mathematical Size Calculation
The script uses this formula to determine ZRAM size:
```bash
ram_gb=$(( RAM_KB / 1024 / 1024 ))
if [ "$ram_gb" -gt 16 ]; then
recommended_mb=$(( ((RAM_KB / 1024 / 1024 + 1) / 4) * 1024 ))
else
recommended_mb=$(( ((RAM_KB / 1024 / 1024 + 1) / 2) * 1024 ))
fi
```
**Breakdown:**
- `RAM_KB`: Total RAM in kilobytes from `/proc/meminfo`
- `/ 1024 / 1024`: Convert KB to MB
- `+ 1`: Add rounding buffer for odd values
- `/ 4`: Target 25% of total RAM on systems with more than 16 GB (avoids excessive RAM reservation on high-memory machines)
- `/ 2`: Target 50% of total RAM on systems with 16 GB or less
- `* 1024`: Round back to nearest MB
**Examples:**
```
System with 32 GB (33554432 KB) RAM (>16 GB):
recommended_mb = ((33554432 / 1024 / 1024 + 1) / 4) * 1024
= ((32 + 1) / 4) * 1024
= (33 / 4) * 1024
= 8 * 1024
= 8192 MB (8 GB)
System with 8 GB (8388608 KB) RAM (<=16 GB):
recommended_mb = ((8388608 / 1024 / 1024 + 1) / 2) * 1024
= ((8 + 1) / 2) * 1024
= (9 / 2) * 1024
= 4 * 1024
= 4096 MB (4 GB)
```
### Priority Configuration (`PRIORITY=100`)
The `swapon` priority determines which swap device the kernel prefers when multiple devices exist:
- **Higher number** = Higher preference (used first by kernel)
- **Default system swap**: Typically 060
- **ZRAM with PRIORITY=100**: Ensures ZRAM is used before physical disk swap
This prevents thrashing where pages bounce between slow disk swap and fast RAM-based ZRAM.
---
## 3. Kernel Parameter Tuning (`sysctl`)
### Essential VM Parameters for Aggressive ZRAM Usage
While the current script focuses on `zram-tools` configuration, optimal performance requires complementary kernel parameter tuning:
```bash
# Recommended sysctl configuration for ZRAM systems
vm.swappiness = 180
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0
```
### Parameter Explanations
| Parameter | Value | Purpose |
|-----------|-------|---------|
| **`vm.swappiness`** | `180200` | Aggressively prefer swap over keeping pages in RAM. Higher values (up to 200) are ideal for ZRAM because it's faster than disk swap. Default 60 is too conservative for memory-constrained systems. |
| **`vm.watermark_boost_factor`** | `0` | Disable additional watermark boosting that could cause premature page reclaim |
| **`vm.watermark_scale_factor`** | `125` | Adjust low-memory watermark thresholds to trigger swap earlier when RAM is constrained |
| **`vm.page-cluster`** | `0` | Disable page clustering. Research shows this reduces unnecessary sequential reads during swap operations, improving ZRAM efficiency by ~15% in gaming workloads |
### Why High Swappiness for ZRAM?
Traditional wisdom suggests keeping swappiness low (2040) to avoid swapping frequently. However:
- **ZRAM is faster than disk**: Microseconds vs milliseconds
- **Thrashing prevention**: Higher swappiness moves pages to ZRAM before they hit slow disk swap
- **Effective RAM expansion**: Compressed pages in ZRAM can store 23x more data, effectively increasing available memory
The Pop!_OS project and Linux kernel documentation both recommend values beyond 100 for in-memory swap scenarios like ZRAM/ZSWAP.
---
## 4. Service Lifecycle and Validation
### Safe Service Initialization
```bash
sudo systemctl restart zramswap
```
**Why `restart` instead of `start`:**
- Ensures previous configuration is cleanly terminated
- Prevents orphaned processes from conflicting with new settings
- Reloads systemd unit files if they were modified during installation
### User Verification Commands
#### Primary: `zramctl` (util-linux)
```bash
sudo zramctl
```
**Output Interpretation:**
```
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 lz4 4G 2.1G 318.6M 424.9M [SWAP]
```
| Column | Meaning |
|--------|---------|
| **NAME** | Device identifier (/dev/zram0) |
| **ALGORITHM** | Active compression algorithm (lz4, zstd, etc.) |
| **DISKSIZE** | Maximum uncompressed data capacity configured |
| **DATA** | Currently stored uncompressed pages in ZRAM |
| **COMPR** | Actual compressed size using physical RAM |
| **TOTAL** | Total memory used including metadata overhead |
| **STREAMS** | Number of active swap streams (typically 4) |
#### Secondary: `swapon --show`
```bash
sudo swapon --show
```
Shows all active swap devices with priority levels. ZRAM should appear with priority matching the configured value (100 in this script).
### Real-Time Monitoring
For continuous monitoring of compression effectiveness:
```bash
# Watch compression ratio changes over time
watch -n 5 'zramctl | grep /dev/zram'
# Monitor memory pressure and swap usage
watch -n 5 'free -h && zramctl'
```
### Troubleshooting Indicators
| Symptom | Likely Cause | Solution |
|---------|--------------|----------|
| `DATA` equals `DISKSIZE` but `COMPR` is near zero | System under memory pressure, ZRAM not being used | Increase `vm.swappiness` or check if physical swap has lower priority |
| High CPU usage with low compression ratio | Incompressible data (e.g., encrypted files) | Consider backing device for incompressible pages |
| Service fails to start | Missing dependencies (`zram-tools`, kernel module) | Run `sudo apt install zram-tools` and verify `modprobe zram` |
### Permanent Configuration
To ensure ZRAM persists across reboots, the script writes configuration to `/etc/default/zramswap`. This file is read by systemd's `zramswap.service` unit at boot time. Additionally, adding the following ensures the kernel module loads:
```bash
echo "zram" | sudo tee /etc/modules-load.d/zram.conf
```
### References:
- [https://docs.kernel.org/admin-guide/blockdev/zram.html](https://docs.kernel.org/admin-guide/blockdev/zram.html)
- [https://wiki.debian.org/ZRam](https://wiki.debian.org/ZRam)
- [https://wiki.archlinux.org/title/Zram](https://wiki.archlinux.org/title/Zram)
- [https://wiki.gentoo.org/wiki/Zram](https://wiki.gentoo.org/wiki/Zram)