使用 LUKS 加密时 NVMe 性能受到影响

mil*_*way 6 linux encryption benchmark luks nvme

我在 Proxmox 主机上运行所有命令,当我 LUKS 加密磁盘时,读取速度提高了 28%,写入速度提高了 66%。我启用了 aes-ni,我应该从硬件加速中获得足够好的性能,所以我真的不知道发生了什么......而且,在未加密的驱动器上写入速度更快是没有意义的。

\n
root@red:/dev/mapper# lsblk\nNAME    MAJ:MIN RM   SIZE RO TYPE MOUNTPOINT\nsda       8:0    0 111.8G  0 disk\n\xe2\x94\x9c\xe2\x94\x80sda1    8:1    0  1007K  0 part\n\xe2\x94\x9c\xe2\x94\x80sda2    8:2    0   512M  0 part\n\xe2\x94\x94\xe2\x94\x80sda3    8:3    0 111.3G  0 part\nsdb       8:16   0 111.8G  0 disk\n\xe2\x94\x9c\xe2\x94\x80sdb1    8:17   0  1007K  0 part\n\xe2\x94\x9c\xe2\x94\x80sdb2    8:18   0   512M  0 part\n\xe2\x94\x94\xe2\x94\x80sdb3    8:19   0 111.3G  0 part\nsdc       8:32   0  12.8T  0 disk\nsdd       8:48   0  12.8T  0 disk\nnvme0n1 259:0    0 465.8G  0 disk\n\nroot@red:/dev/mapper# hdparm -t /dev/nvme0n1\n\n/dev/nvme0n1:\n HDIO_DRIVE_CMD(identify) failed: Inappropriate ioctl for device\n Timing buffered disk reads: 4774 MB in  3.00 seconds = 1591.14 MB/sec\n\nroot@red:/dev/mapper# dd if=/dev/zero of=/dev/nvme0n1 oflag=direct bs=128k count=32k\n32768+0 records in\n32768+0 records out\n4294967296 bytes (4.3 GB, 4.0 GiB) copied, 2.39636 s, 1.8 GB/s\n
Run Code Online (Sandbox Code Playgroud)\n

然后我喜欢加密如下:

\n
root@red:~# cryptsetup luksFormat /dev/nvme0n1\n\nWARNING!\n========\nThis will overwrite data on /dev/nvme0n1 irrevocably.\n\nAre you sure? (Type uppercase yes): YES\nEnter passphrase for /dev/nvme0n1:\nVerify passphrase:\n\nroot@red:~# cryptsetup luksOpen /dev/nvme0n1 Test\nEnter passphrase for /dev/nvme0n1:\n\nroot@red:~# lsblk\nNAME    MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT\nsda       8:0    0 111.8G  0 disk\n\xe2\x94\x9c\xe2\x94\x80sda1    8:1    0  1007K  0 part\n\xe2\x94\x9c\xe2\x94\x80sda2    8:2    0   512M  0 part\n\xe2\x94\x94\xe2\x94\x80sda3    8:3    0 111.3G  0 part\nsdb       8:16   0 111.8G  0 disk\n\xe2\x94\x9c\xe2\x94\x80sdb1    8:17   0  1007K  0 part\n\xe2\x94\x9c\xe2\x94\x80sdb2    8:18   0   512M  0 part\n\xe2\x94\x94\xe2\x94\x80sdb3    8:19   0 111.3G  0 part\nsdc       8:32   0  12.8T  0 disk\nsdd       8:48   0  12.8T  0 disk\nnvme0n1 259:0    0 465.8G  0 disk\n\xe2\x94\x94\xe2\x94\x80Test  253:0    0 465.8G  0 crypt\n\n\nroot@red:~# hdparm -t /dev/mapper/Test\n\n/dev/mapper/Test:\n HDIO_DRIVE_CMD(identify) failed: Inappropriate ioctl for device\n Timing buffered disk reads: 3450 MB in  3.00 seconds = 1149.84 MB/sec\n\nroot@red:~# dd if=/dev/zero of=/dev/mapper/Test oflag=direct bs=128k count=32k\n32768+0 records in\n32768+0 records out\n4294967296 bytes (4.3 GB, 4.0 GiB) copied, 6.83405 s, 628 MB/s\nroot@red:~#\n
Run Code Online (Sandbox Code Playgroud)\n

这是 cryptsetup 的基准测试

\n
root@red:~# cryptsetup benchmark\n#     Algorithm |       Key |      Encryption |      Decryption\n        aes-cbc        128b      1011.6 MiB/s      3031.2 MiB/s\n    serpent-cbc        128b        85.2 MiB/s       646.1 MiB/s\n    twofish-cbc        128b       192.3 MiB/s       354.1 MiB/s\n        aes-cbc        256b       792.4 MiB/s      2475.1 MiB/s\n    serpent-cbc        256b        87.2 MiB/s       648.4 MiB/s\n    twofish-cbc        256b       193.2 MiB/s       355.4 MiB/s\n        aes-xts        256b      1921.2 MiB/s      1919.5 MiB/s\n    serpent-xts        256b       626.2 MiB/s       634.2 MiB/s\n    twofish-xts        256b       349.9 MiB/s       353.1 MiB/s\n        aes-xts        512b      1780.3 MiB/s      1768.5 MiB/s\n    serpent-xts        512b       614.3 MiB/s       637.7 MiB/s\n    twofish-xts        512b       353.2 MiB/s       352.5 MiB/s\n\nroot@red:~# root@red:~# cryptsetup luksDump /dev/nvme0n1\nLUKS header information\nVersion:        2\nEpoch:          3\nMetadata area:  16384 [bytes]\nKeyslots area:  16744448 [bytes]\nUUID:           XXXX\nLabel:          (no label)\nSubsystem:      (no subsystem)\nFlags:          (no flags)\n\nData segments:\n  0: crypt\n    offset: 16777216 [bytes]\n    length: (whole device)\n    cipher: aes-xts-plain64\n    sector: 512 [bytes]\n\nroot@red:~# sort -u /proc/crypto | grep module\nmodule       : aesni_intel\nmodule       : crc32_pclmul\nmodule       : crct10dif_pclmul\nmodule       : cryptd\nmodule       : ghash_clmulni_intel\nmodule       : kernel\nmodule       : serpent_avx2\nmodule       : serpent_avx_x86_64\nmodule       : serpent_generic\nmodule       : serpent_sse2_x86_64\nmodule       : twofish_avx_x86_64\nmodule       : twofish_generic\nmodule       : twofish_x86_64\nmodule       : twofish_x86_64_3way\nroot@red:~#\n
Run Code Online (Sandbox Code Playgroud)\n

我在使用 aes-xts 的基准测试中得到了大约 1700MB/s,所以我想知道为什么驱动器速度会受到如此大的影响?任何帮助将不胜感激!

\n

nei*_*sab 7

来自cryptsetup-benchmark手册页:

注意:此基准测试仅使用内存,仅供参考。您无法从中直接预测真实的存储加密速度。

输出的第一行也暗示了这一点cryptsetup benchmark(重点是我的):

root@archiso ~ # cryptsetup benchmark                                                                  
# Tests are approximate using memory only (no storage IO).
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PBKDF2-sha1      1875806 iterations per second for 256-bit key
...

Run Code Online (Sandbox Code Playgroud)

这就是为什么当实际涉及存储层时您会看到这种差异dd。文件系统类型和挂载选项本身会增加自己的开销,例如在具有 zstd 1 级软压缩的 Btrfs 上:

root@archiso ~ # hdparm -t /dev/nvme0n1 
/dev/nvme0n1:
 HDIO_DRIVE_CMD(identify) failed: Inappropriate ioctl for device
 Timing buffered disk reads: 4658 MB in  3.00 seconds = 1552.45 MB/sec

# cryptsetup luksFormat  /dev/nvme0n1p2
# cryptsetup open --allow-discards !$ luks

# hdparm -t /dev/mapper/luks
/dev/mapper/luks:
 HDIO_DRIVE_CMD(identify) failed: Inappropriate ioctl for device
 Timing buffered disk reads: 3638 MB in  3.00 seconds = 1212.52 MB/sec

# mkfs.btrfs --label btrfs -m dup --csum xxhash /dev/mapper/luks
# mount -t btrfs -o noatime,ssd,compress=zstd:1,autodefrag /dev/disk/by-label/btrfs /mnt
# dd if=/dev/zero of=/mnt/test oflag=direct bs=128k count=32k
32768+0 records in
32768+0 records out
4294967296 bytes (4.3 GB, 4.0 GiB) copied, 7.76791 s, 553 MB/s
Run Code Online (Sandbox Code Playgroud)

没有压缩,我得到的结果与你的类似:

# rm /mnt/test
# umount /mnt
# mount -t btrfs -o noatime,ssd,autodefrag /dev/disk/by-label/btrfs /mnt 
# dd if=/dev/zero of=/mnt/test oflag=direct bs=128k count=32k
32768+0 records in
32768+0 records out
4294967296 bytes (4.3 GB, 4.0 GiB) copied, 6.35182 s, 676 MB/s
Run Code Online (Sandbox Code Playgroud)

这是在具有 Intel core i5-10210U 处理器和 2x4G LPDDR3 2133 MT/s Samsung 内存的 Intel 660p 512G NVMe 驱动器上。确实令人遗憾的是,为了获得软件加密的好处,我们必须放弃 NVMe 存储的如此多的性能。

Cloudflare 在加速 Linux 磁盘加密方面做了一些工作,这些工作已合并到 Linux 5.9 中,并在 5.10.9 中普遍可用,但有报告称,一旦涉及存储,它实际上会损害性能,我可以在自己的用例中证实这一点。

假设您的软件是最新的,您可以使用cryptsetup open

--perf-no_read_workqueue,--perf-no_write_workqueue

绕过 dm-crypt 内部工作队列并同步处理读取或写入请求。

注意:这些选项仅适用于低级 dm-crypt 性能调整,仅当您需要更改默认 dm-crypt 行为时才使用。需要内核 5.9 或更高版本。

上述 Reddit 链接建议启用读取选项,但忽略写入选项。与往常一样,您应该为自己进行测试和基准测试!