LUKS(Universal dm-crypt) 쓰기 성능이 좋지 않음

LUKS(Universal dm-crypt) 쓰기 성능이 좋지 않음

암호화된 블록 장치가거대한성능 손실글쓰기그것에. 몇 시간 동안 웹을 읽고 실험해도 해결책은커녕 적절한 이해도 얻지 못했습니다.

간단히 말해서:btrfs를 블록 장치에 넣으면 매우 빠른 쓰기 속도(~170MB/s)를 얻을 수 있지만 파일 시스템과 블록(~20MB/s) 장치 사이에 dm-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

(두 번째로 캐시에서 파일을 읽은 것 같습니다.)

암호화되지 않은 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

루크스 덤프: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에서는 쓰기 속도가 느려지는 것도 관찰되었습니다.

  • 장치: SanDisk Extreme 64GB USB3.0 USB 메모리 스틱
  • 시스템 1: Intel NUC 5i5RYH, i5-5250U(Broadwell), 8GB RAM, Samsung 840 EVO 250GB SSD
  • 시스템 2: Lenovo 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로 변경하지 못했습니다.
  • LVM 볼륨에 암호화를 넣는 것은 도움이 되지 않습니다.

답변1

답변(현재 제가 아는 한):동시성.

요컨대: 내 거순차적 쓰기, dd파일을 사용하거나 복사할 때(예: 일상적인 사용에서)의사 난수 쓰기(나쁨) 4개의 스레드가 동시에 작동하기 때문에 블록 장치에 동시에 암호화된 암호화된 데이터를 씁니다(좋음).

완화 조치("이전" 커널의 경우)

다음과 같이 IO 스케줄러 대기열에 대기 중인 요청 수를 늘려 부정적인 영향을 완화할 수 있습니다.

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

내 경우 이는 내 질문에 설명된 4GB 무작위 데이터 테스트 처리량(~56MB/s)의 거의 3배에 해당합니다. 물론 암호화되지 않은 IO에 비해 성능은 여전히 ​​100MB/s 미만입니다.

조사

멀티코어blktrace

LUKS 암호화된 블록 장치 위에 btrfs를 배치하는 문제 시나리오를 추가로 조사했습니다. 실제 블록 장치에 어떤 쓰기 명령이 발행되었는지 보여주기 위해 blktrace다음과 같은 것을 사용했습니다.

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

내가 이해할 수 있는 한 이 기능이 수행하는 작업은 /dev/sdc"쓰다" 그런 다음 이를 사람이 읽을 수 있는 출력으로 구문 분석하지만 출력을 추가로 작업으로 제한합니다.""이것은 (에 따르면 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]
  • 첫 번째 열: 블록 장치의 메이저 및 마이너
  • 열 2: CPU ID
  • 열 3: 일련번호
  • 열 4: 타임스탬프
  • 열 5: 프로세스 ID
  • 열 6: 조치
  • 열 7: RWBS 데이터(유형, 섹터, 길이)

dd이것은 마운트된 파일 시스템에 4GB의 무작위 데이터를 로드할 때 생성된 출력의 조각입니다. 분명히 적어도 두 가지 프로세스가 관련되어 있습니다. 나머지 로그는 4개의 프로세서가 모두 실제로 이를 처리하고 있음을 보여줍니다. 안타깝게도 쓰기 요청은 더 이상 정렬되지 않습니다. CPU0이 섹터 38038416 근처에 쓰는 동안 이후에 예약된 CPU1은 섹터 35713872 근처에 쓰고 있습니다. 그 나쁜.

단일 코어blktrace

멀티스레딩을 비활성화하고 CPU의 두 번째 코어를 비활성화한 후 동일한 실험을 수행했습니다. 물론 스틱 쓰기에는 하나의 프로세서만 사용됩니다. 그러나 더 중요한 것은 쓰기 요청의 순서가 올바르게 지정되었기 때문에 동일한 설정에서 약 170MB/s의 전체 쓰기 성능이 달성되었다는 것입니다.

구경하다단일 코어 로그 출력은 약 5,000줄입니다..

논의하다

이제 원인과 올바른 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에게 보내는 모자 팁입니다.

관련 정보