dd 쓰기 속도와 VFS 페이지 캐시에 대해 혼란스러워함

dd 쓰기 속도와 VFS 페이지 캐시에 대해 혼란스러워함

Linux VFS 페이지 캐시 및 dirty_ratioi와 같은 조정 가능한 매개변수에 대한 일부 기사를 읽은 후 페이지 캐시가 읽기 및 쓰기 캐싱 계층으로 작동할 것이라는 인상을 받았습니다.

그러나 아래의 간단한 테스트를 사용하면 페이지 캐시에 있지만 쓰기 작업에서는 작동하지 않는 것 같은 파일의 읽기 속도를 향상시키는 데 효과적입니다.

예를 들어

캐시를 지우고 파일에 씁니다.

# swapoff -a
# echo 3 > /proc/sys/vm/drop_caches

# dd if=/dev/zero of=/home/flo/test bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.182474 s, 172 MB/s

파일이 실제로 페이지 캐시에 있는지 확인하세요.

# vmtouch /home/flo/test 
           Files: 1
     Directories: 0
  Resident Pages: 7680/7680  30M/30M  100%
         Elapsed: 0.000673 seconds

파일에서 읽어 실제로 캐시에서 오는지 확인하세요.

# dd if=/home/flo/test of=/dev/null bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.00824169 s, 3.8 GB/s

캐시를 삭제하고 다시 읽어 속도 차이를 증명하세요.

# echo 3 > /proc/sys/vm/drop_caches
# dd if=/home/flo/test of=/dev/null bs=1M count=30
30+0 records in
30+0 records out
31457280 bytes (31 MB) copied, 0.132531 s, 237 MB/s

나는 dd와 함께 DIRECT_IO를 사용하지 않기 때문에 페이지 캐시가 쓰기 저장 유형의 캐시로 사용될 것으로 예상했습니다. 그리고 기반으로 dirty_ratio또는 dirty_expire_centiseconds... 결국 데이터는 디스크에 커밋됩니다.

특히 쓰기 중에 VFS가 읽기 및 쓰기 프로세스를 어떻게 다르게 처리하는지, 그리고 왜 속도가 향상되지 않는지 설명해 주실 수 있습니까?

예를 들어 RAID 컨트롤러에서 찾을 수 있는 쓰기 저장 캐시처럼 작동하도록 vfs를 쓰기 캐싱에서 더욱 공격적으로 만들 수 있는 방법이 있습니까?

감사합니다

fLo

답변1

auto_da_allocman ext4에는 (no) 옵션 에 대한 소개가 있습니다 .

많은 손상된 응용 프로그램은 fsync()를 사용하지 않습니다...

이 뒤에는 긴 이야기(데이터 손실에 대한 비극)가 있는 것 같습니다. 그것은 다음과 관련이 있습니다지연 할당파일 시스템 블록. Ext2/3에는 그런 기능이 없었지만 ext4뿐만 아니라 상당히 중요한 기능입니다.

응용 프로그램이 동기화되지 않고 사용자도 수동으로 실행하지 않고 커널이 30초 후에만 동기화되면 일부 파일 다시 쓰기가 관련될 때 파일 시스템에서 즉시 동기화하는 것이 좋습니다. 그렇지 않으면 DA를 사용하면 정전 시 쉽게 나쁜 일이 발생할 수 있습니다. 마지막 변경 사항을 잃는 것보다 더 나쁜 것입니다.

conv=notruncatedd 명령이 없으면 덮어쓸 때 "응용 프로그램"처럼 작동합니다. 새 파일을 만들려면 기존 파일을 제거해야 합니다. 그렇지 않으면 기존 파일이 더 길면 혼합된 파일을 얻게 됩니다.

mount -o remount,noauto_da_alloc ...ext4에서 이 동작을 끌 수 있습니다 . 이제 잘라낸 후 오랜 시간이 지나도 블록 쓰기를 수행할 수 있습니다.

다음공격성 수준정기적인 쓰기 저장에 대해 만료 시간을 30초로 늘리고 확인 간격(/proc/sys/vm/의 dirty_..._centisecs 값)을 5초로 늘리는 것입니다. 기본 30/5를 사용하면 매우 빠르게 삭제하지 않는 한 일부 새 파일은 30분 후에 작성됩니다.

VFS가 사용되지 않은 페이지에 대해 더 공격적일수록 파일 시스템은 블록 장치에 대해 덜 공격적이어야 합니다.


마운트 옵션 및 쓰기 저장 매개변수

]# findmnt --real
TARGET       SOURCE     FSTYPE OPTIONS
/            /dev/sda3  ext4   rw,relatime,noauto_da_alloc
|-/root/sda1 /dev/sda1  ext2   rw,relatime
`-/root/16   /dev/sda16 ext4   rw,relatime

이와 같은 설정에서는 덮어쓰기가 sda16에서 즉시 동기화되지만 다른 두 곳에서는 동기화되지 않습니다.

지금은 주기적인 쓰기 저장을 완전히 껐습니다.

]# grep '' /proc/sys/vm/*centisecs
/proc/sys/vm/dirty_expire_centisecs:720000
/proc/sys/vm/dirty_writeback_centisecs:0

그리고 이제 마침내 더티 페이지를 수집하고 있습니다.

]# grep nr_dirty /proc/vmstat 
nr_dirty 10077
nr_dirty_threshold 437320
nr_dirty_background_threshold 174671

노력하다그것들을 모아 어떻게든 기본 배경 비율인 10%에 가깝게 만들기 위해 - 어제 일시 중단 잠자기 모드로 갔을 때 동기화가 이루어졌습니다. 타당합니다. 누가 MB의 더티 페이지를 가지고 자고 싶습니까?

mm/writeback.c세부적으로 매우 복잡하다는 점은 댓글을 통해 알 수 있습니다. 한 가지 문제는 "1000dd가 한 번에 더러워지기 시작"할 때 조절 지점을 놓치지 않는 것입니다. "쓰기 저장"은 장기적으로 약 10% bg 비율을 목표로 하는 것 같습니다. 위의 예에서 볼 수 있듯이 이러한 10%(전체/사용 가능한 RAM)는 일반적인(최소) 사용 시 채우는 데 오랜 시간이 걸립니다. 1분 동안 탐색하면 대략 1000페이지가 더러워집니다.


이론 이후 구체적인 증명

위에 나열된 파일 시스템 중 두 개에서 10개의 블록을 테스트했습니다.

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0076396 s, 1.4 GB/s

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00514406 s, 2.0 GB/s

-> 루트 파티션(위의 sda3)에 noauto_da_alloc을 사용하면 덮어쓰기가 훨씬 더 빨라집니다.

기본 마운트된 ext4(위의 sda16)에서는 속도가 느려집니다.

]# rm test10 

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00800839 s, 1.3 GB/s

]# dd if=/dev/zero of=test10  bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.0740824 s, 142 MB/s

...다음과 같이 전체 덮어쓰기가 동기화되기 때문입니다 vmstat 1 |cut....

    0     0
    0     0
    0     0
-----io----
   bi    bo
    0 10240
    0     0
    0     0

sync지연된 할당을 사용하여 수동으로

좋은 점은 원할 때 수행할 수 있고 단일 파일뿐만 아니라 전체 드라이브에 대해서도 수행할 수 있다는 것입니다.

또한: 마운트 해제, 종료(및 일시 중지)도 포함되어 있습니다.

나쁜 점은 (겹쳐)쓰기와 동기화 사이에 충돌/정전이 발생할 때 길이가 0인 "손상" 위험이 있다는 것입니다. 즉, 외부 저장소에 한 두 개 정도만 저장하면 안전하다는 의미입니다.


결론을 찾을 수 없습니다. 쉬운 해결책은 없고 긴(적어도 논리적인) 설명만 있을 뿐입니다.

답변2

빠른 행동을 보려면 내가 rm test먼저 해야 한다. 예를 들어 dd150MB/s 대신 1GB/s 보고서가 표시됩니다 .

참고자료:

참고 자료에서는 내가 이것을 시도하려고 생각한 이유만 설명하지만 실제로 IO가 차단되는 이유는 설명하지 않습니다.

내 컴퓨터에서는 차단이 2016년에 추가된 새로운 WBT("writeback throttling") 코드 내에서만 발생하는 것처럼 보였습니다.~ 후에당신은 당신의 질문을했습니다. 분석해본적은 없는데이것이 원인이 될 것입니다. 그리고 WBT가 비활성화되면 사라졌습니다.

내 커널 버전은 4.18.16-200.fc28.x86_64.

strace -T모든 시간이 close()에서 소비되었음을 알 수 있는데, 이는 나에게 가장 의미가 있습니다. 저도 사용해 보았습니다 perf. 예상대로 작동하지 않았지만 다음과 같은 스택 추적이 표시되었습니다.

dd 17068 [003] 475165.381526:       sched:sched_switch: dd:17068 [120] T ==> kworker/3:1H:19326 [100]
    ffffffffa390c172 __sched_text_start+0x352 ([kernel.kallsyms])
    ffffffffa390c172 __sched_text_start+0x352 ([kernel.kallsyms])
    ffffffffa390c6a8 schedule+0x28 ([kernel.kallsyms])
    ffffffffa30def32 io_schedule+0x12 ([kernel.kallsyms])
    ffffffffa3461ed7 wbt_wait+0x337 ([kernel.kallsyms])
    ffffffffa342ee33 blk_queue_bio+0x123 ([kernel.kallsyms])
    ffffffffa342d114 generic_make_request+0x1a4 ([kernel.kallsyms])
    ffffffffa342d3c5 submit_bio+0x45 ([kernel.kallsyms])
    ffffffffa3377d78 ext4_io_submit+0x48 ([kernel.kallsyms])
    ffffffffa335da2c ext4_writepages+0x70c ([kernel.kallsyms])
    ffffffffa3209311 do_writepages+0x41 ([kernel.kallsyms])
    ffffffffa31f808e __filemap_fdatawrite_range+0xbe ([kernel.kallsyms])
    ffffffffa334b9ec ext4_release_file+0x6c ([kernel.kallsyms])
    ffffffffa32a9d4e __fput+0xae ([kernel.kallsyms])
    ffffffffa30cf474 task_work_run+0x84 ([kernel.kallsyms])
    ffffffffa3003e6e exit_to_usermode_loop+0xce ([kernel.kallsyms])
    ffffffffa300425d do_syscall_64+0x14d ([kernel.kallsyms])
    ffffffffa3a00088 entry_SYSCALL_64_after_hwframe+0x44 ([kernel.kallsyms])
        7fcca3a60654 __close+0x14 (/usr/lib64/libc-2.27.so)

deadline이는 내가 현재 WBT("writeback throttling")를 활성화한 상태에서 I/O 스케줄러를 테스트하고 있다는 것을 상기시켜주었습니다 . WBT를 비활성화하면(호환되지 않는 CFQ로 전환 포함) 다시 빠른 동작이 가능해졌습니다!

perf내가 이것을 보는 데 사용한 명령은 다음과 같습니다 .

sudo perf record -e sched:sched_stat_sleep -e sched:sched_switch -e sched:sched_process_exit -gP -o ~/perf.data dd if=/dev/zero of=test bs=1M count=30
sudo perf script -i ~/perf.data | cat

답변3

. dd​예를 들어, 사용하면 cp쓰기에 대한 페이지 캐시를 얻을 수 있습니다.

관련 정보