dd 파이프라인에 대한 gunzip이 느려지는 이유는 무엇입니까?

dd 파이프라인에 대한 gunzip이 느려지는 이유는 무엇입니까?

내 명령:

gunzip -c serial2udp.image.gz |
sudo dd of=/dev/mmcblk0 conv=fsync,notrunc status=progress bs=4M

내 결과:

15930949632 bytes (16 GB, 15 GiB) copied, 1049 s, 15.2 MB/s    

0+331128 records in
0+331128 records out
15931539456 bytes (16 GB, 15 GiB) copied, 1995.2 s, 8.0 MB/s

카드: SanDisk Ultra 32GB MicroSDHC Class 10 UHS 메모리 카드 속도 최대 30MB/s
릴리스: 16.0.4 xenial(xfce 포함)
커널 버전: 4.13.0.37-generic

내가 읽은 내용에 따르면 17분 정도 소요되는 것이 합리적이라고 생각됩니다. 블록 크기를 조정해도 큰 차이는 없는 것 같습니다(bs=100M은 여전히 ​​비슷한 타임스탬프에서 이 동작을 나타냅니다). 업데이트가 중단되고 이후 16분 동안 완료된 보고서가 생성되지 않는 이유는 무엇입니까?

iotop은 mmcqd/0이 현재(99% IO) 백그라운드에서 여전히 실행 중이라고 알려주므로 어딘가에 마지막 5MB를 보관하는 캐시가 있다고 생각하지만 fsync는 그런 일이 발생하지 않도록 해야 한다고 생각합니다 iotop이 dd를 보여줍니다. 현재로서는 교차로도 없습니다. ctrl-c는 거의 쓸모가 없습니다. 쓰기 후에 드라이브를 손상시키고 싶지 않습니다.

답변1

마지막 5MB를 보관하는 캐시가 어딘가에 있을 것 같은데, fsync가 이런 일이 발생하지 않도록 해야 한다고 생각합니다.

conv=fsyncfsync모든 데이터가 작성된 후 호출하여 모든 캐시를 다시 쓰는 것을 나타냅니다 . dd마지막에 매달리는 것이 바로 그 일입니다.

출력 파일이 입력 파일보다 느린 경우 기록된 데이터가 dd캐시에 누적될 수 있습니다. 커널 캐시는 때때로 시스템 RAM의 상당 부분을 채울 수 있습니다. 이는 매우 잘못된 진행 정보를 생성합니다. "마지막 5MB"는 dd진행 상황을 보여주는 아티팩트일 뿐입니다.

시스템이 약 8GB(쓰기 데이터 16GB의 절반)를 캐시한다면 약 32GB의 RAM이 있거나 일부 커널 옵션을 조정해야 한다고 생각합니다. 아래 lwn.net 링크를 참조하세요. 동의합니다. 15분 동안 진행 상황 정보를 받지 못하는 것은 꽤 실망스럽습니다.

다른 명령을 사용할 수 있습니다 dd. 더 정확한 진행 상황을 보여주고 싶다면 dd더 많은 복잡성을 받아들여야 할 수도 있습니다. 현실은 나와 다를 수 있지만 다음 사항으로 인해 귀하의 성과가 저하되지 않기를 바랍니다.

gunzip -c serial2udp.image.gz |
dd iflag=fullblock bs=4M |
sudo dd iflag=fullblock oflag=direct conv=fsync status=progress bs=4M of=/dev/mmcblk0
  • oflag=direct iflag=fullblock커널 캐시는 완전히 우회하므로 스택을 쌓지 마십시오.
  • iflag=fullblockAFAIK는 이와 같은 명령에 필요합니다(예를 들어 파이프에서 읽고 직접 IO를 사용하여 쓰기 때문에). 누락의 영향은 fullblock또 다른 불행한 합병증입니다 dd. 이 사이트의 일부 게시물은 이를 사용하여 항상 다른 명령을 사용하는 것을 선호해야 한다고 주장합니다. 그러나 직접 또는 동기식 IO를 수행하는 다른 방법을 찾는 것은 어렵습니다.
  • conv=fsync계속 사용해야 합니다. 답장해 주세요.장비은닉처.
  • 디스크 쓰기와 병렬로 압축이 풀린 출력을 버퍼링하기 위해 dd뒤에 추가를 추가했습니다 . 이는 성능을 복잡하게 하거나 조금 복잡하게 gunzip만드는 문제 중 하나입니다 . 일반 IO(비직접, 비동기)에는 이미 커널 캐시에 의해 버퍼링되어 있으므로 이것이 필요하지 않습니다. 4M 쓰기 저장 캐시가 있는 하드 드라이브에 쓰는 경우 추가 버퍼도 필요하지 않을 수 있지만 SD 카드에는 그렇게 많은 버퍼가 없다고 생각합니다.oflag=directoflag=sync

사용할 수도 있습니다 oflag=direct,sync(필요하지 않음 conv=fsync). 이상한 출력 장치가 있는 경우 좋은 진행 정보를 제공하는 데 유용할 수 있습니다.수백 메가바이트의 캐시. 그러나 일반적으로 나는 oflag=sync이것이 성능에 잠재적인 방해가 된다고 봅니다.

2013년 기사가 있네요https://lwn.net/Articles/572911/그것은 당신과 같은 몇 분의 지연을 언급합니다. 많은 사람들은 몇 분 동안 write-back 데이터를 캐시하는 이 기능이 바람직하지 않다고 생각합니다. 문제는 캐시 크기 제한이 빠른 장치와 느린 장치에 무차별적으로 적용된다는 점입니다. 장치 속도는 데이터 위치에 따라 달라지므로 커널이 장치 속도를 측정하는 것은 쉽지 않습니다. 예를 들어, 캐시된 쓰기가 임의의 위치에 분산되어 있으면 하드 드라이브가 쓰기 헤드를 반복적으로 이동하는 데 더 오랜 시간이 걸립니다.

업데이트가 중단되는 이유

이는 fsync()전체 범위에 적용되는 단일 시스템 호출입니다.문서장비. 완료될 때까지 상태 업데이트가 반환되지 않습니다.

답변2

을(를) 사용하고 싶습니다 fullblock. notrunc장치 파일에는 영향을 미치지 않습니다.

dd of=/dev/mmcblk0 iflag=fullblock status=progress bs=4M

답변3

답변 자체는 아니지만 진단에 더 가깝습니다. 파이프 뷰 유틸리티 사용pv각 파이프라인의 유량 변화를 확인하고,예를 들어:

pv -c -N raw serial2udp.image.gz |
gunzip |
pv -c -N uncompressed |
sudo dd of=/dev/mmcblk0 conv=fsync,notrunc status=progress bs=4M

가정:

  1. 마지막 부분에서 속도가 느린 경우 .gz파일이 마지막 부분에서 가장 많이 압축되었거나 gunzip더 많은 작업이 필요할 가능성이 높습니다.
  2. 또 다른 가능성은 쓰기 매체 자체가 디자인의 특성이나 심지어 불량/한계 블록으로 인해 특정 부분에서 속도가 느려진다는 것입니다. 비파괴적인 읽기/쓰기 테스트는 다음을 통해 수행할 수 있습니다.badblocks -nv /dev/mmcblk0

관련 정보