web-dev-qa-db-ja.com

Abysmal General dm-crypt(LUKS)書き込みパフォーマンス

書き込みの場合、ブロックデバイスを暗号化すると巨大パフォーマンスが低下する問題を調査しています。インターネットで何時間も読んだり実験したりしても、適切な理解は得られず、解決策もありませんでした。

質問の要約: btrfsをブロックデバイスに配置すると書き込み速度が完全に高速になる(〜170MB/s)一方で、dmを書き込むと書き込み速度が急激に低下する(〜20MB/s)のはなぜですか-crypt/LUKSはファイルシステムとブロックデバイスの間にありますが、システムは十分に高い暗号化スループットを維持できる以上のものですか?

シナリオ

/home/schlimmchen/randomは、以前の/dev/urandomからのデータで満たされた4.0GBファイルです。

dd if=/dev/urandom of=/home/schlimmchen/Documents/random bs=1M count=4096

それを読むのは超高速です:

$ dd if=/home/schlimmchen/Documents/random of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 6.58036 s, 648 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 0.786102 s, 5.4 GB/s

(2回目は、ファイルは明らかにキャッシュから読み取られました)。

暗号化されていないbtrfs

デバイスはbtrfsで直接フォーマットされます(ブロックデバイスにパーティションテーブルはありません)。

$ Sudo mkfs.btrfs /dev/sdf
$ Sudo mount /dev/sdf /mnt
$ Sudo chmod 777 /mnt

書き込み速度は最大170MB/sになります。

$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test1 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 27.1564 s, 157 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test2 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 25.1882 s, 169 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test3 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 29.8419 s, 143 MB/s

読み取り速度は200MB/sをはるかに上回ります。

$ dd if=/mnt/dd-test1 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 19.8265 s, 215 MB/s
$ dd if=/mnt/dd-test2 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 19.9821 s, 213 MB/s
$ dd if=/mnt/dd-test3 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 19.8561 s, 215 MB/s

ブロックデバイス上の暗号化されたbtrfs

デバイスはLUKSでフォーマットされ、結果のデバイスはbtrfsでフォーマットされます。

$ Sudo cryptsetup luksFormat /dev/sdf
$ Sudo cryptsetup luksOpen /dev/sdf crypt
$ Sudo mkfs.btrfs /dev/mapper/crypt
$ Sudo mount /dev/mapper/crypt /mnt
$ Sudo chmod 777 /mnt
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test1 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 210.42 s, 20.3 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test2 bs=1M 
4265841146 bytes (4.3 GB) copied, 207.402 s, 20.6 MB/s

読み取り速度の低下はごくわずかです(なぜそれが起こるのですか?):

$ dd if=/mnt/dd-test1 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 22.2002 s, 192 MB/s
$ dd if=/mnt/dd-test2 of=/dev/null bs=1M
4265841146 bytes (4.3 GB) copied, 22.0794 s, 193 MB/s

luksDump: http://Pastebin.com/i9VYRR0p

ブロックデバイス上のbtrfs上のファイル内の暗号化されたbtrfs

暗号化されたファイルに書き込む場合、書き込み速度は150MB/s以上に「急上昇」します。私はbtrfsをブロックデバイスに置き、16GBのファイルを割り当て、それをlukfsFormatしてマウントしました。

$ Sudo mkfs.btrfs /dev/sdf -f
$ Sudo mount /dev/sdf /mnt
$ Sudo chmod 777 /mnt
$ dd if=/dev/zero of=/mnt/crypted-file bs=1M count=16384 conv=fsync
17179869184 bytes (17 GB) copied, 100.534 s, 171 MB/s
$ Sudo cryptsetup luksFormat /mnt/crypted-file
$ Sudo cryptsetup luksOpen /mnt/crypted-file crypt
$ Sudo mkfs.btrfs /dev/mapper/crypt
$ Sudo mount /dev/mapper/crypt /tmp/nested/
$ dd if=/home/schlimmchen/Documents/random of=/tmp/nested/dd-test1 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 26.4524 s, 161 MB/s
$ dd if=/home/schlimmchen/Documents/random of=/tmp/nested/dd-test2 bs=1M conv=fsync
4265841146 bytes (4.3 GB) copied, 27.5601 s, 155 MB/s

なぜこのように書き込みパフォーマンスが向上するのですか?ファイルシステムとブロックデバイスのこの特定の入れ子は、高速書き込みを支援するために何を実現しますか?

セットアップ

この問題は、同じディストリビューションとカーネルを実行している2つのシステムで再現可能です。ただし、System2のカーネル3.19.0では書き込み速度が遅いことも確認しました。

  • デバイス:SanDisk Extreme 64GB USB3.0 USB Stick
  • System1:Intel NUC 5i5RYH、i5-5250U(Broadwell)、8GB RAM、Samsung 840 EVO 250GB SSD
  • System2:Lenovo T440p、i5-4300M(Haswell)、16GB RAM、Samsung 850 PRO 256GB SSD
  • Distro/Kernel:Debian Jessie、3.16.7
  • cryptsetup:1.6.6
  • /proc/crypto for System1: http://Pastebin.com/QUSGMfiS
  • cryptsetup benchmark for System1: http://Pastebin.com/4RxzPFeT
  • btrfs(-tools)はバージョン3.17です
  • lsblk -t /dev/sdfhttp://Pastebin.com/nv49tYWc

考え

  • アラインメントはnot私が見る限りの原因です。スティックのページサイズが16KiBであっても、cryptsetupペイロードの開始はとにかく2MiBに揃えられます。
  • --allow-discards(cryptsetupのluksOpen用)は、私が期待していたとおり、役に立ちませんでした。
  • USB3.0アダプターを介して接続された外付けハードドライブを使用して、非常に少ない実験を行ったところ、非常によく似た動作が観察されました。
  • システムは64KiBブロックを書き込んでいるようです。 A systemtrap script 私が試したのは、少なくともそれを示しています。 /sys/block/sdf/statは、多くの書き込みがマージされるため、この仮説を裏付けています。だから、私の推測では、小さすぎるブロックで書くことが原因ではないと思います。
  • ブロックデバイスのキュースケジューラをNOOPに変更しても運がありません。
  • クリプトをLVMボリュームに入れることは助けにはなりませんでした。
24
schlimmchen

答え(私の知っているとおり):concurrency

簡単に言えば:My sequential write 、using dd or when when copying a file(毎日のように...)、疑似ランダム書き込み(不良)になります。これは、4つのスレッドが同時に暗号化された後、ブロックデバイスに暗号化されたデータを書き込む際に動作しているためです(良い) 。

緩和(「古い」カーネルの場合)

次のようにIOスケジューラキューのキューに入れられた要求の量を増やすことにより、悪影響を軽減できます。

echo 4096 | Sudo tee /sys/block/sdc/queue/nr_requests

私の場合、これは私の質問で説明した4GBランダムデータテストのスループットをほぼ3倍(約56MB/s)にします。もちろん、暗号化されていないIOと比較して、パフォーマンスは依然として100MB/sを下回っています。

調査

マルチコアblktrace

さらに、btrfsがLUKS暗号化ブロックデバイスの上に配置される問題のあるシナリオを調査しました。実際のブロックデバイスに発行された書き込み命令を示すために、次のようにblktraceを使用しました。

Sudo blktrace -a write -d /dev/sdc -o - | blkparse -b 1 -i - | grep -w D

これが行うことは(私が理解できた限り)trace IO /dev/sdcへのリクエストで、タイプは[ write )です。 、次にこれを人間が読める出力に解析しますが、出力をアクション " [〜#〜] d [〜#〜] "に制限します。これは(man blkparseに従って) )「ドライバに発行されたIO 」。

結果はこのようなものでした( マルチコアログの出力の約5000行 を参照):

8,32   0    32732   127.148240056     3  D   W 38036976 + 240 [ksoftirqd/0]
8,32   0    32734   127.149958221     3  D   W 38038176 + 240 [ksoftirqd/0]
8,32   0    32736   127.160257521     3  D   W 38038416 + 240 [ksoftirqd/0]
8,32   1    30264   127.186905632    13  D   W 35712032 + 240 [ksoftirqd/1]
8,32   1    30266   127.196561599    13  D   W 35712272 + 240 [ksoftirqd/1]
8,32   1    30268   127.209431760    13  D   W 35713872 + 240 [ksoftirqd/1]
  • 列1:ブロックデバイスのメジャー、マイナー
  • 列2:CPU ID
  • 列3:シーケンス番号
  • 列4:タイムスタンプ
  • 列5:プロセスID
  • 列6:アクション
  • 列7:RWBSデータ(タイプ、セクター、長さ)

これは、4GBのランダムデータをマウントされたファイルシステムにdd '実行しているときに生成される出力の一部です。少なくとも2つのプロセスが関与していることは明らかです。残りのログは、4つのプロセッサすべてが実際に動作していることを示しています。悲しいことに、書き込み要求はもう順序付けされていません。 CPU0が38038416番目のセクター周辺のどこかに書き込んでいる間、後でスケジュールされるCPU1は、35713872番目のセクターのどこかに書き込んでいます。それは良くないね。

シングルコアblktrace

マルチスレッドを無効にし、CPUの2番目のコアを無効にした後、同じ実験を行いました。もちろん、スティックへの書き込みに関与するプロセッサは1つだけです。しかし、さらに重要なことは、書き込み要求が適切にシーケンシャルであるため、それ以外の場合は同じセットアップで約170MB/sの完全な書き込みパフォーマンスが達成される理由です。

シングルコアログの出力の約5000行 をご覧ください。

討論

原因と適切なgoogle検索用語がわかったので、この問題に関する情報が浮上しています。結局のところ、私が最初に気づくのは私ではありません。

現在のカーネルで修正(> = 4.0.2)

私は(後で) カーネルコミット が明らかにこの正確な問題を対象としていることを発見したので、更新されたカーネルを試してみたかったのです。 [自分でコンパイルして、それがdebian/sidにあることを確認した後]問題は実際に修正されたことがわかります。修正が行われた正確なカーネルリリースはわかりませんが、 元のコミット は、興味のある人に手掛かりを与えます。

記録のために:

$ uname -a
Linux t440p 4.0.0-1-AMD64 #1 SMP Debian 4.0.2-1 (2015-05-11) x86_64 GNU/Linux
$ dd if=/home/schlimmchen/Documents/random of=/mnt/dd-test bs=1M conv=fsync
4294967296 bytes (4.3 GB) copied, 29.7559 s, 144 MB/s

コミットを書いたMikulas Patockaへの帽子先端。

21
schlimmchen