This commit is contained in:
JMARyA 2024-12-20 12:46:21 +01:00
parent adc93877f4
commit 5c4b3e14bf
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263

202
technology/linux/Zram.md Normal file
View file

@ -0,0 +1,202 @@
---
obj: concept
arch-wiki: https://wiki.archlinux.org/title/Zram
source: https://docs.kernel.org/admin-guide/blockdev/zram.html
wiki: https://en.wikipedia.org/wiki/Zram
rev: 2024-12-20
---
# Zram
zram, formerly called compcache, is a Linux kernel module for creating a compressed block device in RAM, i.e. a RAM disk with on-the-fly disk compression. The block device created with zram can then be used for swap or as a general-purpose RAM disk. The two most common uses for zram are for the storage of temporary files (`/tmp`) and as a swap device. Initially, zram had only the latter function, hence the original name "compcache" ("compressed cache").
## Usage as swap
Initially the created zram block device does not reserve or use any RAM. Only as files need or want to be swapped out, they will be compressed and moved into the zram block device. The zram block device will then dynamically grow or shrink as required.
Even when assuming that zstd only achieves a conservative 1:2 compression ratio (real world data shows a common ratio of 1:3), zram will offer the advantage of being able to store more content in RAM than without memory compression.
### Manually
To set up one zstd compressed zram device with half the system memory capacity and a higher-than-normal priority (only for the current session):
```sh
modprobe zram
zramctl /dev/zram0 --algorithm zstd --size "$(($(grep -Po 'MemTotal:\s*\K\d+' /proc/meminfo)/2))KiB"
mkswap -U clear /dev/zram0
swapon --discard --priority 100 /dev/zram0
```
To disable it again, either reboot or run:
```sh
swapoff /dev/zram0
modprobe -r zram
echo 1 > /sys/module/zswap/parameters/enabled
```
For a permanent solution, use a method from one of the following sections.
### Using a udev rule
The example below describes how to set up swap on zram automatically at boot with a single udev rule. No extra package should be needed to make this work.
Explicitly load the module at boot:
```ini
# /etc/modules-load.d/zram.conf
zram
```
Create the following udev rule adjusting the disksize attribute as necessary:
```
# /etc/udev/rules.d/99-zram.rules
ACTION=="add", KERNEL=="zram0", ATTR{comp_algorithm}="zstd", ATTR{disksize}="4G", RUN="/usr/bin/mkswap -U clear /dev/%k", TAG+="systemd"
```
Add `/dev/zram` to your fstab with a higher than default priority:
```
# /etc/fstab
/dev/zram0 none swap defaults,discard,pri=100 0 0
```
### Using zram-generator
`zram-generator` provides `systemd-zram-setup@zramN.service` units to automatically initialize zram devices without users needing to enable/start the template or its instances.
To use it, install `zram-generator`, and create `/etc/systemd/zram-generator.conf` with the following:
```ini
# /etc/systemd/zram-generator.conf
[zram0]
zram-size = min(ram / 2, 4096)
compression-algorithm = zstd
```
`zram-size` is the size (in MiB) of zram device, you can use ram to represent the total memory.
`compression-algorithm` specifies the algorithm used to compress in zram device.
`cat /sys/block/zram0/comp_algorithm` gives the available compression algorithm (as well as the current one included in brackets).
Then run `daemon-reload`, start your configured `systemd-zram-setup@zramN.service` instance (`N` matching the numerical instance-ID, in the example it is `systemd-zram-setup@zram0.service`).
You can check the swap status of your configured `/dev/zramN` device(s) by reading the unit status of your `systemd-zram-setup@zramN.service` instance(s), by using `zramctl`, or by using `swapon`.
## zramctl
zramctl is used to quickly set up zram device parameters, to reset zram devices, and to query the status of used zram devices.
Usage:
```sh
# Get info:
# If no option is given, all non-zero size zram devices are shown.
zramctl [options]
# Reset zram:
zramctl -r zramdev...
# Print name of first unused zram device:
zramctl -f
# Set up a zram device:
zramctl [-f | zramdev] [-s size] [-t number] [-a algorithm]
```
### Options
| Option | Description |
| ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `-a, --algorithm lzo/lz4/lz4hc/deflate/842/zstd` | Set the compression algorithm to be used for compressing data in the zram device. The list of supported algorithms could be inaccurate as it depends on the current kernel configuration. A basic overview can be obtained by using the command `cat /sys/block/zram0/comp_algorithm`; |
| `-f, --find` | Find the first unused zram device. If a `--size` argument is present, then initialize the device. |
| `-n, --noheadings` | Do not print a header line in status output. ` |
| `-o, --output list` | Define the status output columns to be used. If no output arrangement is specified, then a default set is used. See below for list of all supported columns. |
| `--output-all` | Output all available columns. |
| `--raw` | Use the raw format for status output. |
| `-r, --reset` | Reset the options of the specified zram device(s). Zram device settings can be changed only after a reset. |
| `-s, --size size` | Create a zram device of the specified size. Zram devices are aligned to memory pages; when the requested size is not a multiple of the page size, it will be rounded up to the next multiple. When not otherwise specified, the unit of the size parameter is bytes. |
| `-t, --streams number` | Set the maximum number of compression streams that can be used for the device. The default is use all CPUs and one stream for kernels older than 4.6. |
### Output Columns
| Output | Description |
| ------------ | ------------------------------------------------------------------ |
| `NAME` | zram device name |
| `DISKSIZE` | limit on the uncompressed amount of data |
| `DATA` | uncompressed size of stored data |
| `COMPR` | compressed size of stored data |
| `ALGORITHM` | the selected compression algorithm |
| `STREAMS` | number of concurrent compress operations |
| `ZERO-PAGES` | empty pages with no allocated memory |
| `TOTAL` | all memory including allocator fragmentation and metadata overhead |
| `MEM-LIMIT` | memory limit used to store compressed data |
| `MEM-USED` | memory zram has consumed to store compressed data |
| `MIGRATED` | number of objects migrated by compaction |
| `COMP-RATIO` | compression ratio: DATA/TOTAL |
| `MOUNTPOINT` | where the device is mounted |
## Misc
### Checking zram statistics
Use zramctl. Example:
```
$ zramctl
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL STREAMS MOUNTPOINT
/dev/zram0 zstd 32G 1.9G 318.6M 424.9M 16 [SWAP]
DISKSIZE = 32G: this zram device will store up to 32 GiB of uncompressed data.
DATA = 1.9G: currently, 1.9 GiB (uncompressed) of data is being stored in this zram device
COMPR = 318.6M: the 1.9 GiB uncompressed data was compressed to 318.6 MiB
TOTAL = 424.9M: including metadata, the 1.9 GiB of uncompressed data is using up 424.9 MiB of physical RAM
```
### Multiple zram devices
By default, loading the zram module creates a single `/dev/zram0` device.
If you need more than one `/dev/zram` device, specify the amount using the `num_devices` kernel module parameter or add them as needed afterwards.
### Optimizing swap on zram
Since zram behaves differently than disk swap, we can configure the system's swap to take full potential of the zram advantages:
```ini
# /etc/sysctl.d/99-vm-zram-parameters.conf
vm.swappiness = 180
vm.watermark_boost_factor = 0
vm.watermark_scale_factor = 125
vm.page-cluster = 0
```
### Enabling a backing device for a zram block
zram can be configured to push incompressible pages to a specified block device when under memory pressure.
To add a backing device manually:
```sh
echo /dev/sdX > /sys/block/zram0/backing_dev
```
To add a backing device to your zram block device using `zram-generator`, update `/etc/systemd/zram-generator.conf` with the following under your `[zramX]` device you want the backing device added to:
```ini
# /etc/systemd/zram-generator.conf
writeback-device=/dev/disk/by-partuuid/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
```
### Using zram for non-swap purposes
zram can also be used as a generic RAM-backed block device, e.g. a `/dev/ram` with less physical memory usage, but slightly lower performance. However there are some caveats:
- There is no partition table support (no automatic creation of `/dev/zramxpy`).
- The block size is fixed to 4 kiB.
The obvious way around this is to stack a loop device on-top the zram, using [losetup](../applications/cli/system/losetup.md), specifying the desired block size using the `-b` option and the `-P` option to process partition tables and automatic creation of the partition loop devices.
```sh
zramctl -f -s <SIZE>G
```
Copy the disk image to the new `/dev/zramx`, then create a loop device. If the disk image has a partition table, the block size of the loop device must match the block size used by the partition table, which is typically 512 or 4096 bytes.
```sh
losetup -f -b 512 -P /dev/zramx
mount /dev/loop0p1 /mnt/boot
mount /dev/loop0p2 /mnt/root
```