11 KiB
obj | arch-wiki | source | wiki | rev |
---|---|---|---|---|
concept | https://wiki.archlinux.org/title/Zram | https://docs.kernel.org/admin-guide/blockdev/zram.html | https://en.wikipedia.org/wiki/Zram | 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):
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:
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:
# /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:
# /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:
# 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:
# /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:
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:
# /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, 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.
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.
losetup -f -b 512 -P /dev/zramx
mount /dev/loop0p1 /mnt/boot
mount /dev/loop0p2 /mnt/root