
Linux VFS 페이지 캐시 및 dirty_ratio
i와 같은 조정 가능한 매개변수에 대한 일부 기사를 읽은 후 페이지 캐시가 읽기 및 쓰기 캐싱 계층으로 작동할 것이라는 인상을 받았습니다.
그러나 아래의 간단한 테스트를 사용하면 페이지 캐시에 있지만 쓰기 작업에서는 작동하지 않는 것 같은 파일의 읽기 속도를 향상시키는 데 효과적입니다.
예를 들어
캐시를 지우고 파일에 씁니다.
# 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_alloc
man ext4에는 (no) 옵션 에 대한 소개가 있습니다 .
많은 손상된 응용 프로그램은 fsync()를 사용하지 않습니다...
이 뒤에는 긴 이야기(데이터 손실에 대한 비극)가 있는 것 같습니다. 그것은 다음과 관련이 있습니다지연 할당파일 시스템 블록. Ext2/3에는 그런 기능이 없었지만 ext4뿐만 아니라 상당히 중요한 기능입니다.
응용 프로그램이 동기화되지 않고 사용자도 수동으로 실행하지 않고 커널이 30초 후에만 동기화되면 일부 파일 다시 쓰기가 관련될 때 파일 시스템에서 즉시 동기화하는 것이 좋습니다. 그렇지 않으면 DA를 사용하면 정전 시 쉽게 나쁜 일이 발생할 수 있습니다. 마지막 변경 사항을 잃는 것보다 더 나쁜 것입니다.
conv=notruncate
dd 명령이 없으면 덮어쓸 때 "응용 프로그램"처럼 작동합니다. 새 파일을 만들려면 기존 파일을 제거해야 합니다. 그렇지 않으면 기존 파일이 더 길면 혼합된 파일을 얻게 됩니다.
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
먼저 해야 한다. 예를 들어 dd
150MB/s 대신 1GB/s 보고서가 표시됩니다 .
참고자료:
auto_da_alloc
~에남자 ext4.- LWN.net 기사 "ext4 및 데이터 손실".
- 이 경우 XFS는 동일하지만 ext4가 수행하는 다른 경우에서는 그렇지 않습니다(기존 파일에 대해 이름 바꾸기).https://www.spinics.net/lists/xfs/msg36717.html.
참고 자료에서는 내가 이것을 시도하려고 생각한 이유만 설명하지만 실제로 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
쓰기에 대한 페이지 캐시를 얻을 수 있습니다.