概要

RAMディスク代わりにzramを使うことに興味を持ったが、 インターネット上の日本語で書かれたzramの記事では、zramの性能を測定するのにファイルシステムを作成していて キャッシュが効いていそうなものばかりだったため、ddで直接測定した。

実験にはlinux-6.12のソースコードのtarファイルを用いた。実験した圧縮アルゴリズムで最速だったlz4で読込1.2GB/s、書込490MB/s、圧縮比3.06であった。 実験に使ったi3 8100Tは古いCPUとはいえ、tmpfsが読取10GB/s、書込2.4GB/sであることを考えるとzramはI/Oが遅い。 I/O性能が必要な場合、tmpfsをzramで置き換えることは慎重に検討するべきである。

導入

zramはlinuxのメモリ上に作成できる圧縮ブロックデバイスで、swapやRAMディスクとして使用できる。 zramに書き込まれたデータは圧縮されるので、そのI/O性能はCPUと圧縮アルゴリズムとデータの特徴に依る。

Linux 6.12で使用できるアルゴリズムはlzo-rle,lzo,lz4,lz4hc,zstd,deflate,842であり、 どれもLZ系の圧縮アルゴリズムである。 LZ系のアルゴリズムでは、繰り返し同じパターンが現れるデータのとき高い圧縮率になる。 例えば、ソースコードやログファイルなどで高い圧縮率を期待できる。

zramでは、同じデータ(unsigned long)で埋められたページはsame pageとして処理され、圧縮処理を行わない。 same pageの展開は圧縮されたページの展開よりも速いので、ゼロフィルされたファイルを用いればzramの処理速度の上界が把握できるはずである。

そこで、zramの最大I/O速度を測定するために適当な大きさのゼロフィルされたファイルを用い測定し、 アルゴリズムを含めた実力を測るためにソースコードを纏めた非圧縮のtarファイルを用い測定することとした。

zramはブロックデバイスなため、ファイルを書き込むときは通常はext4などのファイルシステムを用いるが、ファイルシステムを通したI/Oはページキャッシュが効くため速度測定では注意を払う必要がある。 今回は、簡単に測定をするため、デバイスファイルに直接ddでファイルの書き込み・読み取りを行う。

実験環境

機種はLenovo M720q(i3-8100T/DDR4-2400 32GB)を用いた。 カーネルはLinux version 6.12.38-gentoo-distを用いた。 実験時はCPU governerをperformanceに設定して測定した。

実験用データはlinux-6.12.tar.xzを伸長したlinux-6.12.tarを使用した。

ddのオプションはbs=1Mで測定した。 読み取り速度測定時はof=/dev/nullに出力した。 実験用ファイルはtmpfs上に配置した。

実験内容と結果

実験1 tmpfsの速度測定

RAMディスクとしてのtmpfs(正確にはファイルシステムだが)の性能を測るため、tmpfs上でのI/O速度を測定した。 tmpfs上に配置したlinux-6.12.tarを、ddでコピーすることで書き込み速度を、ddで/dev/nullに出力することで読み取り速度を測定した。

結果は読取9.8GB/s、書込2.2GB/sであった。

実験2 0埋めファイルの測定

ddで/dev/zeroからtmpfs上に1GiBのファイルを作成し、測定に用いた。

結果は読取2.7GB/s, 書込4.3GB/sであった。

実験3 ソースコードtarファイルの測定

linux-6.12.tarをtmpfs上に配置して測定に用いた。 圧縮アルゴリズムのlevelはデフォルト値を用いた(lz4は1, lz4hcは9, zstdは3, deflateは6)。

圧縮アルゴリズム 読取 書込 圧縮比
lzo-rle 900 MB/s 460 MB/s 3.17
lzo 890 MB/s 459 MB/s 3.17
lz4 1.2 GB/s 490 MB/s 3.06
lz4hc 1.3 GB/s 63.5 MB/s 3.45
zstd 433 MB/s 160 MB/s 4.42
deflate 231 MB/s 33.4 MB/s 4.63
842 100 MB/s 52.0 MB/s 2.14

圧縮アルゴリズムの性能はデータの特性に依るところが大きいので、あくまでも参考程度に留めるべきである。

考察

実験2の結果のうち、書込がtmpfsよりも速い。これはzramがsame pageを実際にはメモリに書き込まないためと考えられる。 読込がtmpfsに比べ遅いのは、same page読込時にページを毎回memset_lで埋めるのが原因だと思うが、詳細はわからない。

実験3の結果は、lz4とzstdを比較すると、圧縮比は1.44倍改善する代わりにI/Oのスループットがおよそ1/3に低下している。 メモリ制限が厳しくCPUに余裕のあるシステムであればzstdが良いが、一般的な用途にはlz4のほうが適していると考えられる。 ただし、データの特性によって性能が変化するため、今回の結果を全ての条件下で適用できるわけではないことに留意が必要である。

結論

次のような場合、RAMディスクとしてのzramはtmpfsに比べて有利である。

  • メモリ制限が厳しい場合(組み込みなど)
  • データを圧縮できる場合(揮発性のログディレクトリなど)
  • I/O性能がそれほど重要視されないRAMディスク用(portage TMPDIRなど)

zramのI/Oはtmpfsに比べ遅いが、実運用ではファイルシステムを通して利用するため、キャッシュが効けばtmpfsと同程度に高速になることに留意が必要である。

感想

lz4が速いことは知っていたが、圧縮比も意外と悪くなかった。 時折見かける記事ではzstdのほうがlzoより速いという記述が見られるが、今回はzstdのほうが遅かった。

記事には載せなかったが、zstdのlevelを振ったとき、level=1で書込速度が1.2倍になったが圧縮比が2.4%悪化した。 データの特性に大きく影響されるとはいえ、zstdはlz4やlzoほど速くはないという結論になった。 もちろんzstdでもzramはランダムアクセスに強いし、HDDやeMMCに比べれば十分に速い。

842はPOWERプロセッサとかだと速いのかもしれないが、x86_64で選ぶ理由は無いように見える。

今回はRAMディスクとしてzramを用いる前提で実験をしたが、zramをswapとして使う場合は基本的にlz4で、メモリが少ないなどの事情があるならzstdを検討する位でいい気がする。 また、tmpfsのほうがzramよりも高速なこと、tmpfsはswapに書き出せることから、一般的な用途ではRAMディスクにはtmpfsを採用した上でzram swapを設定するとよい。

今回の測定結果だけを見ればzramよりNVMeのほうが速いような気もしてくるが、ランダムアクセス時のIOPSはzramのほうが圧倒的に速いとか、 NVMeよりzramのほうがレイテンシが1桁以上小さいとかの話もあるので、今後はそのあたりも含めて測定したい。 https://github.com/ublue-os/bazzite/issues/1570