
zram 実践入門 - 圧縮スワップの効果測定と「優先度でティアリング」の落とし穴
メモリ管理の全体像を掴むならまずこれ。
ページ回収の内側まで踏み込みたいとき。
システムコール側から確認したい人に。
当サイトは Amazon.co.jp を宣伝しリンクすることで紹介料を得る手段を提供する、Amazonアソシエイト・プログラムの参加者です。価格・在庫はリンク先の最新情報をご確認ください。
メモリが足りないサーバーに対する対策として、スワップを増やすのは素直な発想です。ただしディスクスワップは遅く、増やしたところで「ページを読み戻すたびにディスクI/Oが発生する」という性質は変わりません。
そこで出てくるのがzramです。RAMの一部を圧縮領域として切り出し、そこをスワップデバイスとして使う仕組みで、ディスクI/Oがゼロのまま実効メモリを増やせます。
この記事では、実際にメモリ2GBの本番VPSにzramを導入して測定した結果をもとに、zramの仕組み、mm_stat の読み方、そしてよく紹介される設定手順に含まれる設計上の落とし穴までを整理します。結論を先に言うと、zramは確かに効きましたが、「zramを高優先度、ディスクスワップを低優先度にすれば自動で階層化される」という説明は正しくありません。
NOTE
測定環境はさくらのVPS上のUbuntu、カーネル 5.15.0-181-generic、物理メモリ1,963MB、Next.jsのプロセスが66本常駐している状態です。記事中の mm_stat / zramctl / swapon / zswapのdebugfs統計の出力は、2026年9月2日にこの環境で実際に取得した値です。仕様の記述はカーネル公式ドキュメントで確認しています。なお本記事の執筆後、同じサーバーを実際にzswapへ切り替えました。その手順と実測値は「追記: 実際に zswap へ切り替えた」にまとめてあります。
zram とは何か
zramは、RAM上に確保した領域を圧縮して使う仮想ブロックデバイスです。カーネルのドキュメントでは、圧縮によって「非常に高速なI/O」と「相応のメモリ節約」が得られる仕組みとして説明されています。作られたデバイスは /dev/zram0 のように見え、スワップにもファイルシステムにも使えます。
スワップとして使った場合の流れはこうなります。
- カーネルがページを追い出そうとする
- 追い出し先がzramなら、そのページを圧縮してRAM内に置く
- 読み戻すときは伸長してRAMへ戻す
ディスクは一切触りません。代わりにCPUを使って圧縮・伸長します。「メモリをCPU時間と引き換えに増やす」仕組みだと考えると分かりやすいです。
仮想メモリとページングそのものの仕組みは仮想メモリとページングの仕組みにまとめてあるので、ページフォルトやページ回収の前提が曖昧な場合はそちらを先に読んでください。
ディスクスワップとの違い
| ディスクスワップ | zram | |
|---|---|---|
| 保存先 | ディスク(SSD/HDD) | RAM |
| 容量 | ディスクの空き次第 | RAMの一部を消費 |
| 速度 | ディスクI/O律速 | メモリ速度+圧縮コスト |
| 実効的な増分 | 確保したぶん全部 | 圧縮率に応じた差分のみ |
| SSD書き込み | 発生する | 発生しない |
重要なのは最後から2番目の行です。12GBのディスクスワップは12GB使えますが、1GBのzramが増やすメモリは1GBではありません。圧縮データはRAMを消費するので、増えるのは「元のサイズ - 圧縮後のサイズ」の差分だけです。ここは後で実測値を見ます。
導入手順
Ubuntu 24.04での手順です。zramはカーネルモジュールとして提供されており、追加パッケージは不要でした。
# 1. モジュールを読み込む
sudo modprobe zram num_devices=1
# 2. 使える圧縮アルゴリズムを確認する
cat /sys/block/zram0/comp_algorithmこの環境での出力です。角括弧が現在の選択を示します。
lzo [lzo-rle] lz4 lz4hc 842 zstd既定は lzo-rle でした。今回は圧縮率を優先して zstd を選びます。
# 3. アルゴリズムとサイズを設定する(disksize より先に comp_algorithm を書く)
echo zstd | sudo tee /sys/block/zram0/comp_algorithm
echo 1G | sudo tee /sys/block/zram0/disksize
# 4. スワップとして初期化・有効化する
sudo mkswap /dev/zram0
sudo swapon --priority 100 /dev/zram0comp_algorithm はデバイスの初期化前、つまり disksize を書く前に設定する必要があります。順序を逆にすると変更が効きません。
サイズの決め方
カーネルのドキュメントには次のように書かれています。
there is little point creating a zram of greater than twice the size of memory since we expect a 2:1 compression ratio
(2対1の圧縮率を見込んでいるので、メモリの2倍を超えるzramを作る意味はほとんどない)
一方でFedoraは、systemdのzram-generatorの既定として物理メモリの50%(上限8GB)を採用しています。Fedora 34で、それまでの「25%・上限4GB」から引き上げられました。
今回の環境は物理1,963MBで、しかもすでに1.4GBが使用中という厳しい状況です。zramの圧縮データはRAMを食うため、いきなり大きく取ると本末転倒になります。そこで1GBから始めました。満杯になっても、後述の実測圧縮率なら消費は300MB程度で収まる計算です。
もう1つ、ドキュメントには見落としやすい注記があります。
zram uses about 0.1% of the size of the disk when not in use so a huge zram is wasteful
(未使用時でもディスクサイズの約0.1%を使うので、巨大なzramは無駄になる)
実測: どれだけ効いたか
有効化してから約1時間後の zramctl の出力です。
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL
/dev/zram0 zstd 1G 336.9M 96.9M 101.5M337MBぶんのページが、97MBまで圧縮されて格納されています。圧縮率は約3.5倍で、実際に取り戻せたメモリは約235MBです。Next.jsのヒープのようなテキスト主体のデータは、zstdでよく縮みます。
導入前後のメモリの余裕はこう変わりました。
| 指標 | 導入前 | 導入後 |
|---|---|---|
| MemAvailable | 185〜224MB | 283〜425MB |
1GBのzramで235MBを取り戻した、というのが正味の効果です。繰り返しになりますが、1GB確保しても1GB増えるわけではありません。
mm_stat の読み方
zramctl は要約なので、詳しく見るには /sys/block/zram0/mm_stat を読みます。空白区切りで9個の値が並びます。
352944128 101482495 106319872 0 264155136 2578 18245 1644 47174カーネルドキュメントに定義されている並び順は次のとおりです。
| # | フィールド | この環境の値 | 意味 |
|---|---|---|---|
| 1 | orig_data_size | 336.6 MiB | 圧縮前のデータ量 |
| 2 | compr_data_size | 96.8 MiB | 圧縮後のデータ量 |
| 3 | mem_used_total | 101.4 MiB | 実際に確保したメモリ(断片化とメタデータ込み) |
| 4 | mem_limit | 0 | 上限設定(0は無制限) |
| 5 | mem_used_max | 251.9 MiB | これまでの最大消費量 |
| 6 | same_pages | 2,578 | 同一要素で埋まったページ。メモリを消費しない |
| 7 | pages_compacted | 18,245 | コンパクションで解放されたページ数 |
| 8 | huge_pages | 1,644 | 現在の非圧縮ページ数 |
| 9 | huge_pages_since | 47,174 | 起動以降の累計 |
実務で見るべき点を3つ挙げます。
1つ目は2番目と3番目の差です。圧縮後96.8 MiBに対して実際の確保は101.4 MiBで、4.6 MiBがアロケータの断片化とメタデータのオーバーヘッドです。節約量を計算するときは compr_data_size ではなく mem_used_total を使わないと、5%前後を見誤ります。
2つ目は huge_pagesです。ドキュメントは「どのアルゴリズムでも圧縮できなかったページ」と定義しています。この環境では1,644ページ、全体の約2%でした。すでに圧縮済みの画像や暗号化データが多いワークロードでは、この比率が上がって圧縮率が落ちます。導入前に効果を見積もりたいなら、ここを見るのが早いです。
3つ目は mem_used_maxです。現在101.4 MiBでも、ピークでは251.9 MiBまで使っていました。サイジングは現在値ではなくピークで考える必要があります。
なお same_pages は、ゼロで埋まったページなど同一要素だけのページで、メモリを一切消費しません。仮想マシンや起動直後のプロセスが多い環境では、ここがかなりの数になります。
落とし穴: 「優先度でティアリング」は成立しない
ここからが本題です。
zramの解説記事でよく見かけるのが、次の構成です。
sudo swapon --priority 100 /dev/zram0 # 速いので先に使う
# ディスクswapは低い優先度のまま残す説明としては「まず高速なzramに退避し、溢れたぶんだけディスクに落ちる二段構え」となります。私も今回この構成で入れました。実際の swapon --show はこうなっています。
NAME TYPE SIZE USED PRIO
/swapfile file 4G 3.7G -2
/swapfile2 file 8G 3G -3
/swapfile3 file 12G 0B -4
/dev/zram0 partition 1024M 338M 100ところが、これは階層化として機能しません。カーネルのメモリ管理に詳しいChris Downは、2026年3月の記事でこの構成を明確な誤りとして挙げています。理由はLRU反転です。
何が起きるかというと、こうです。
- 優先度が高いzramが先に埋まる。埋まるのは、たいてい起動直後の初期化データのような古くて冷たいページ
- zramが満杯になる
- その後に追い出される比較的新しくて熱いページは、行き場がディスクスワップしかない
- 結果として、冷たいページが高速なRAMを占有し、熱いページが遅いディスクに置かれる
本来LRUが実現したいこと(熱いものを速い層に、冷たいものを遅い層に)の真逆になります。しかもzramには、いったん入れたページを後からディスクへ追い出す仕組みが標準では働きません。優先度はあくまで「どこに書くかの順番」を決めるだけで、格納済みのページを層の間で移動させる機能ではないのです。
上の出力で /dev/zram0 が338M / 1024Mと、まだ余裕がある状態なのは、zramを入れたのが1時間前だからにすぎません。満杯に達した時点で、この問題が始まります。
writeback は解決策になるか
zramには backing_dev と writeback という機能があり、指定したブロックデバイスへページを書き出せます。理屈のうえでは階層化できます。
ただし実運用では、専用パーティションの用意、アイドル判定のしきい値決め、定期実行するスクリプトの整備が必要です。しかもカーネルのページ回収機構とは連動しないため、メモリ需要が急に立ち上がる場面で間に合いません。前掲の記事はこれを「メモリ管理のIKEA」(自分で組み立てる必要がある)と表現しています。
zram と zswap の使い分け
同じ「圧縮スワップ」でも、zswapは設計がまったく違います。
| zram | zswap | |
|---|---|---|
| 位置づけ | 独立したブロックデバイス | ディスクswapの前段キャッシュ |
| 非圧縮ページ | そのまま格納する | 検出してディスクへ直行させる |
| 階層化 | 手動、または実質なし | カーネルが自動で行う |
| cgroupへの計上 | されない | される |
| ディスクswap | 必須ではない | 必須(前段キャッシュなので) |
| 限界に達したとき | 硬直しやすい | 段階的に劣化する |
zswapはディスクスワップの前に置くキャッシュなので、冷たくなったページをカーネルが自分の判断でディスクへ落とせます。LRU反転が起きないのはこのためです。非圧縮ページを検出してディスクへ回す点も、RAMとCPUの両方を節約します。
前掲の記事は、迷ったらzswapを選ぶべきだとしたうえで、zramが適するのは次のような場合だと整理しています。
- ディスクを持たない組み込み機器(スワップデバイスが1つしかない)
- 意図的にディスクを持たない設計で、systemd-oomdのようなユーザー空間のOOMデーモンと組み合わせる場合
- Androidのように、zram前提で徹底的にチューニングされたワークロード
- プライベートなデータを永続ストレージに一切書きたくない場合
なお、zramとzswapを同時に有効にしてはいけません。どちらも圧縮キャッシュなので、二重に持つと個別に使うより多くのメモリを消費します。
現在の状態は次のコマンドで確認できます。切り替え前のこの環境では、zswapは無効で、既定のまま lzo と zbud が選択されていました。
cat /sys/module/zswap/parameters/enabled # N なら無効
cat /sys/module/zswap/parameters/compressor # lzo
cat /sys/module/zswap/parameters/zpool # zbudcgroupへの計上の差は、コンテナを動かす環境では効いてきます。zramの消費はcgroupから見えないため、コンテナごとのメモリ制限が実態と合わなくなります。cgroupによるリソース制限の仕組みはLinuxコンテナの仕組み入門にまとめてあります。
swappiness をどう決めるか
zramを入れたら vm.swappiness も見直す価値があります。カーネルのドキュメントは、この値を次のように定義しています。
This control is used to define the rough relative IO cost of swapping and filesystem paging.
(スワップとファイルシステムのページングの、おおまかな相対I/Oコストを定義するための制御である)
既定値は60、有効範囲は0から200です。100が「スワップとファイルシステムのI/Oコストが等価」を意味する中立点で、それより大きい値は「スワップのほうが安い」ことを示します。
ドキュメントには具体的な計算例まで書かれています。
if the random IO against the swap device is on average 2x faster than IO from the filesystem, swappiness should be 133 (x + 2x = 200, 2x = 133.33)
(スワップデバイスへのランダムI/Oが平均してファイルシステムの2倍速いなら、swappinessは133にすべきである)
zramはRAM上にあるのでディスクより桁違いに速く、この式に素直に当てはめれば200に近い値になります。実際、zram-generatorの swap-priority の既定が100に設定されているのも、「zramを遅いスワップデバイスより優先させる」ためだと説明されています。
ただし注意が必要です。swappinessを上げるとzramへの退避だけでなく、ディスクスワップへの流入も増えます。前節のLRU反転を抱えたままswappinessを上げると、問題を加速させることになります。構成を整理してから触るべきパラメータです。
関連して vm.page-cluster もあります。スワップから一度に読み戻すページ数を2の冪で指定するもので、既定は3(8ページ)です。zramはシークコストがないため先読みの利点が薄く、Arch Wikiなどでは0(1ページ)にする設定が紹介されています。ただしこちらもワークロード依存なので、変更するなら測定とセットにしてください。
再起動後も有効にする
modprobe と swapon は再起動で消えます。永続化の方法は2つあります。
systemd-zram-generator を使う(推奨)
systemdプロジェクトが提供する公式のジェネレータで、Fedoraが既定で採用しているものです。設定ファイルを置くだけで済みます。
# /etc/systemd/zram-generator.conf
[zram0]
zram-size = min(ram / 2, 4096)
compression-algorithm = zstd
swap-priority = 100zram-size は式で書けるので、メモリ搭載量が違うマシンでも同じ設定を使い回せます。
自前の systemd ユニットを書く
パッケージを追加したくない場合はこちらです。今回の環境ではメモリの余裕がなく、パッケージ導入を避けたかったのでこの方法を採りました。
# /etc/systemd/system/zram-swap.service
[Unit]
Description=zram compressed swap (zstd 1G, priority 100)
After=multi-user.target
DefaultDependencies=no
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/sbin/modprobe zram
ExecStart=/bin/bash -c "echo zstd > /sys/block/zram0/comp_algorithm && echo 1G > /sys/block/zram0/disksize && /sbin/mkswap /dev/zram0 && /sbin/swapon --priority 100 /dev/zram0"
ExecStop=/bin/bash -c "/sbin/swapoff /dev/zram0 && echo 1 > /sys/block/zram0/reset"
[Install]
WantedBy=multi-user.targetモジュール自体も起動時に読ませます。
echo zram | sudo tee /etc/modules-load.d/zram.conf
sudo systemctl daemon-reload
sudo systemctl enable zram-swap.serviceユニットを書いたら systemd-analyze verify で構文を確認しておくと安全です。
sudo systemd-analyze verify /etc/systemd/system/zram-swap.serviceなお、すでにzramが有効な状態で systemctl start を実行すると、初期化済みのデバイスに対して mkswap が走って失敗します。起動経路の検証は、swapoff してから行うか、次回再起動時に確認することになります。
追記: 実際に zswap へ切り替えた
この記事を書いた数時間後、同じサーバーでzramをやめてzswapに切り替えました。手順と実測値を残しておきます。
切り替えを決めた理由
導入から数時間後のzramはこうなっていました。
NAME ALGORITHM DISKSIZE DATA COMPR TOTAL
/dev/zram0 zstd 1G 904.1M 246.6M 257.9M904.1MB / 1024MBで、ほぼ満杯です。圧縮率3.67倍という数字自体は優秀ですが、ここから先に追い出されるページはすべてディスクswapへ直行します。前述のLRU反転が始まる直前でした。数時間で埋まったという事実そのものが、この構成が階層化として機能していないことの実証になっています。
手順1: zram を空にする
一番慎重を要する工程です。swapoff は、zramに載っている916MBのページを読み戻す必要があります。この時点のMemAvailableは125MBしかありませんでした。
先に受け皿を確認します。
free -m | awk '/Swap/{print "ディスクswapの空き:", $4, "MB"}'
sudo dd if=/dev/zero of=/tmp/ddtest bs=1M count=100 oflag=directディスクswapの空きは18,402MB、書き込みは233MB/sでした。余裕があると判断して実行します。SSHが切れても中断しないよう、サーバー側でデタッチして走らせるのが安全です。
sudo nohup bash -c 'swapoff /dev/zram0; echo "rc=$?"' > /tmp/zram-swapoff.log 2>&1 &推移です。
| 経過 | zramのデータ量 | MemAvailable | load average |
|---|---|---|---|
| 20秒 | 677.1MB | 69MB | 5.84 |
| 40秒 | 488.8MB | 111MB | 8.74 |
| 60秒 | 174.1MB | 77MB | 15.41 |
| 80秒 | 68KB | 116MB | 13.55 |
| 160秒 | 68KB | 182MB | 3.67 |
所要2分、rc=0 で完了しました。loadは一時15.41まで上がりましたが、OOMは起きていません。zramが排出されるにつれて確保していた257.9MBのRAMが解放されるため、見た目ほどメモリは苦しくなりません。
排出後、デバイスを解放して自動起動も止めます。
echo 1 | sudo tee /sys/block/zram0/reset
sudo systemctl disable --now zram-swap.service
sudo rm -f /etc/modules-load.d/zram.conf
sudo rmmod zram手順2: パラメータを選ぶ(既定のままは損)
ここが見落とされがちです。Ubuntu 24.04・カーネル5.15の既定値はこうでした。
| パラメータ | 既定 | 選んだ値 | 理由 |
|---|---|---|---|
| compressor | lzo | zstd | 圧縮率が高い |
| zpool | zbud | zsmalloc | zbudは1ページに最大2個までしか詰められず密度が低い |
| max_pool_percent | 20 | 20(据え置き) | RAM 1,963MBに対して最大392MB |
既定の lzo と zbud のままでは、zswapの利点を大きく取りこぼします。特にzpoolの差は効きます。使えるアルゴリズムは /proc/crypto で確認できます。
grep -c '^name : zstd' /proc/crypto # 1 なら利用可この環境では zstd lzo lzo-rle deflate が使え、lz4 はありませんでした。
手順3: 有効化する
順序が重要です。enabled より先に zpool と compressor を設定します。
sudo modprobe zsmalloc
echo zsmalloc | sudo tee /sys/module/zswap/parameters/zpool
echo zstd | sudo tee /sys/module/zswap/parameters/compressor
echo 1 | sudo tee /sys/module/zswap/parameters/enabled永続化はカーネルパラメータで指定するのが正攻法です。
zswap.enabled=1 zswap.compressor=zstd zswap.zpool=zsmallocただしブート設定を触りたくない場合は、systemdユニットでも代替できます。swapが有効になる前に走らせるのがポイントです。
# /etc/systemd/system/zswap.service
[Unit]
Description=Enable zswap (zstd + zsmalloc)
DefaultDependencies=no
After=sysinit.target
Before=swap.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStartPre=/sbin/modprobe zsmalloc
ExecStart=/bin/bash -c "echo zsmalloc > /sys/module/zswap/parameters/zpool && echo zstd > /sys/module/zswap/parameters/compressor && echo 1 > /sys/module/zswap/parameters/enabled"
ExecStop=/bin/bash -c "echo 0 > /sys/module/zswap/parameters/enabled"
[Install]
WantedBy=sysinit.target効果測定は debugfs で見る
zswapには mm_stat にあたるファイルがありません。統計はdebugfsに置かれています。
sudo mountpoint -q /sys/kernel/debug || sudo mount -t debugfs none /sys/kernel/debug
ls /sys/kernel/debug/zswap/主なファイルは次のとおりです。
| ファイル | 意味 |
|---|---|
| stored_pages | 現在格納しているページ数 |
| pool_total_size | プールが実際に使っているメモリ量(バイト) |
| same_filled_pages | 同一要素で埋まったページ数 |
| written_back_pages | プールから追い出してディスクswapへ書き戻したページ数 |
| pool_limit_hit | プールが上限に達した回数 |
| reject_compress_poor | 圧縮率が悪くて拒否したページ数 |
| reject_alloc_fail | 確保に失敗した回数 |
圧縮率は stored_pages × 4096 ÷ pool_total_size で求まります。
実測結果
有効化後の推移です。
stored= 16380p( 64.0MB) pool= 17.0MB 圧縮=3.76倍 書戻=0 上限=0 不良=0
stored= 26073p( 101.8MB) pool= 28.4MB 圧縮=3.59倍 書戻=0 上限=0 不良=0
stored= 36911p( 144.2MB) pool= 42.0MB 圧縮=3.43倍 書戻=0 上限=0 不良=0144.2MBのページが42.0MBに収まり、圧縮率は3.43倍でした。zramのときの3.5倍とほぼ同等です。同じzstdなので当然ではありますが、zpoolに zsmalloc を選ばず既定の zbud のままだと、ここまでの密度は出ません。
reject_compress_poor reject_alloc_fail reject_reclaim_fail pool_limit_hit はいずれも0で、健全に動作しています。
見るべき指標
日常的に見るなら written_back_pages です。これが増えていれば、プールが上限に達してカーネルが自動でディスクswapへ落としている状態を意味します。これがzramには無かった機能そのもので、優先度の設定をしなくても階層化が働いている証拠になります。
pool_limit_hit や reject_alloc_fail が増え続けるようなら、max_pool_percent が小さすぎるか、そもそもメモリが足りていません。
1行で確認できるようにしておくと便利です。
d=/sys/kernel/debug/zswap
echo "stored=$(cat $d/stored_pages) pool=$(cat $d/pool_total_size) 書戻=$(cat $d/written_back_pages) 上限=$(cat $d/pool_limit_hit)"切り替えてみての所感
移行コストは、実質的に swapoff の2分間だけでした。逆に言えばzramに載っているページ量が多いほど、この2分が長く重くなります。切り替えるなら、zramが埋まりきる前の早い段階のほうが安全です。
そして設定項目が減ったのが大きい点です。zramでは優先度、サイズ、writebackのしきい値、swappinessの相互作用を考える必要がありましたが、zswapは有効にしてcompressorとzpoolを選べば、あとはカーネルが階層化を判断します。前掲の記事が「迷ったらzswap」と書いている理由が、運用してみるとよく分かります。
結局どう使えばよいか
今回の測定と一次情報を踏まえた整理です。
zramが素直に効くケース- スワップデバイスがzramだけ(ディスクスワップを併用しない)
- ディスクを持たない、または持ちたくない環境
- 圧縮の効くデータが主体(テキスト、コード、JSONなど)
- メモリ不足の緊急避難として、短期的に凌ぎたい場合
- すでにディスクスワップがあり、これからも使う
- cgroupでメモリを管理している(コンテナ環境)
- 手動チューニングを増やしたくない
- 圧縮の効かないデータが主体(暗号化済み、圧縮済みメディア)
- ワーキングセットそのものがRAMを大きく超えている
最後の点は強調しておきます。zramは冷たいページを圧縮して置いておくための仕組みであって、頻繁にアクセスされるページを増やす仕組みではありません。アクティブなワーキングセットがRAMに収まらない状況では、圧縮と伸長のCPUコストが乗るぶん、かえって遅くなることもあります。
今回の環境で235MBを取り戻せたのは、66本のNode.jsプロセスの大半がアイドルで、そのヒープが「めったに触られない、しかしよく圧縮できるデータ」だったからです。条件が違えば結果も変わります。導入したら必ず mm_stat で圧縮率と huge_pages を確認してください。
そしてスワップ全般に言えることですが、これは時間を買う手段であって、メモリ不足そのものの解決ではありません。ディスクスワップの作り方についてはLinux のスワップファイルは fallocate で速く作るにまとめてあります。
まとめ
- zramはRAMの一部を圧縮領域にして使う仮想ブロックデバイス。ディスクI/Oなしで実効メモリを増やせる
- 実測では337MBが97MBに圧縮され、圧縮率3.5倍、実効235MBの節約。ただし1GB確保しても1GB増えるわけではない
- 効果測定は
mm_statを見る。節約量はcompr_data_sizeではなくmem_used_totalで計算し、huge_pagesで非圧縮ページの比率を、mem_used_maxでピークを確認する - 「zramを優先度100、ディスクswapを低優先度」はLRU反転を招く。優先度は書き込み先の順序を決めるだけで、格納済みページを層間で移動させる機能ではない
- ディスクスワップを併用するなら、zramではなくzswapのほうが設計として素直。ただし両方を同時に有効にしてはいけない
vm.swappinessはカーネル文書に計算例がある。ただしLRU反転を抱えたまま上げると問題を加速させる- 実際にこのサーバーはzswapへ切り替えた。916MBの
swapoffに2分(loadは一時15.41まで上昇、OOMなし)、切り替え後の圧縮率は3.43倍でzramと同等 - zswapは既定の
lzoとzbudのままでは利点を取りこぼす。zstdとzsmallocを、enabledより先に設定する - zswapの統計は
mm_statではなくdebugfs(/sys/kernel/debug/zswap/)にある。日常的に見るのはwritten_back_pagesで、増えていれば階層化が働いている


