Performance

糟糕的通用 dm-crypt (LUKS) 寫入性能

  • May 16, 2015

我正在調查一個問題,即加密塊設備在寫入時會造成****巨大的性能損失。數小時的網際網路閱讀和實驗並沒有為我提供正確的理解,更不用說解決方案了。

**簡而言之:**為什麼將 btrfs 放入塊設備(~170MB/s)時寫入速度非常快,而將 dm-crypt/LUKS 置於塊設備之間時寫入速度下降(~20MB/s)文件系統和塊設備,儘管系統能夠維持足夠高的加密吞吐量?

設想

/home/schlimmchen/random是一個 4.0GB 的文件,其中填充了/dev/urandom之前的數據。

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

(第二次,文件顯然是從記憶體中讀取的)。

未加密的 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

為什麼寫入性能會這樣提高?文件系統和塊設備的這種特殊嵌套對提高寫入速度有什麼幫助?

設置

在執行相同發行版和核心的兩個系統上可以重現該問題。但是,我還觀察到 System2 上核心 3.19.0 的低寫入速度。

  • 設備:閃迪至尊 64GB USB3.0 USB 記憶棒
  • 系統 1:英特爾 NUC 5i5RYH、i5-5250U (Broadwell)、8GB RAM、三星 840 EVO 250GB SSD
  • System2:聯想 T440p、i5-4300M (Haswell)、16GB RAM、三星 850 PRO 256GB SSD
  • 發行版/核心:Debian Jessie,3.16.7
  • 密碼設置:1.6.6
  • /proc/crypto對於系統 1:http: //pastebin.com/QUSGMfiS
  • cryptsetup benchmark對於系統 1:http: //pastebin.com/4RxzPFeT
  • btrfs(-tools) 是 3.17 版
  • lsblk -t /dev/sdf: http://pastebin.com/nv49tYWc

想法

  • 據我所知,對齊不是原因。即使儲存棒的頁面大小為 16KiB,cryptsetup 有效負載的開始也始終與 2MiB 對齊。
  • --allow-discards(對於 cryptsetup 的 luksOpen)沒有幫助,正如我所料。
  • 雖然用它做的實驗少得多,但我觀察到通過 USB3.0 適配器連接的外部硬碟驅動器的行為非常相似。
  • 在我看來,系統正在寫入 64KiB 塊。我試過的一個系統陷阱腳本至少表明了這一點。/sys/block/sdf/stat支持這個假設,因為很多寫入被合併。所以我的猜測是寫太小塊不是原因。
  • 將塊設備隊列調度程序更改為 NOOP 可不行。
  • 將 crypt 放入 LVM 卷沒有幫助。

答案(據我所知):並發

簡而言之:我的順序寫入,無論是使用dd還是在復製文件時(例如…在日常使用中),都變成了偽隨機寫入(壞),因為四個執行緒在並發後同時將加密數據寫入塊設備加密(好)。

緩解(對於“舊”核心)

可以通過增加 IO 調度程序隊列中的排隊請求數量來減輕負面影響,如下所示:

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

在我的情況下,這幾乎是我的問題中解釋的 4GB 隨機數據測試的吞吐量的三倍(~56MB/s)。當然,與未加密的 IO 相比,性能仍然低於 100MB/s。

調查

多核blktrace

我進一步研究了將 btrfs 放置在 LUKS 加密塊設備頂部的問題場景。為了向我展示向實際塊設備發出的寫入指令,我blktrace這樣使用:

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

這樣做是(據我所知)跟踪/dev/sdc類型為“ write ”的 IO 請求,然後將其解析為人類可讀的輸出,但進一步將輸出限制為操作“ 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 數據(類型、扇區、長度)

這是dd將 4GB 隨機數據寫入已掛載的文件系統時產生的輸出的片段。顯然,至少涉及兩個過程。剩下的日誌顯示所有四個處理器實際上都在處理它。可悲的是,不再對寫入請求進行排序。當 CPU0 在第 38038416 扇區附近寫入時,稍後安排的 CPU1 正在在第 35713872 扇區附近寫入。那很糟。

單核blktrace

在禁用多執行緒並禁用 CPU 的第二個核心後,我做了同樣的實驗。當然,只有一個處理器參與寫入記憶棒。但更重要的是,寫入請求是正確順序的,這就是為什麼在其他相同的設置中可以實現 ~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 致敬。

引用自:https://unix.stackexchange.com/questions/203677