쓰기 저장 캐시("더티")가 제한이 시작되는 예상 임계값 아래로 제한되는 것 같습니다. 그 한계는 무엇입니까?

쓰기 저장 캐시("더티")가 제한이 시작되는 예상 임계값 아래로 제한되는 것 같습니다. 그 한계는 무엇입니까?

이전 Q&A에서 dirty_ratio에 대한 실험을 보여드린 적이 있습니다.

쓰기 저장 캐시("더티")는 dirty_Background_ratio보다 훨씬 작은 것으로 제한되는 것 같습니다. 그 한계는 무엇입니까? 이 한도는 어떻게 계산되나요?

더러운 요금 계산에 대한 이해를 바로잡아 문제를 해결했다고 생각합니다. 하지만 방금 실험을 반복했는데 다시 쓰기 캐시가 이전에 본 것보다 낮게 조절되었습니다. 이 문제를 해결할 수 없습니다. 문제를 제한하는 것은 무엇입니까?

sysctl에 대한 기본값이 있습니다 vm.dirty*. dirty_background_ratio10이요, dirty_ratio20이요. "비율"은 MemFree+ 의 백분율로 표시되는 더티 페이지 캐시(즉, 다시 쓰기 캐시)의 크기를 나타냅니다 Cached. 그들은아니요백분율 MemTotal- 위의 질문에서 제가 혼란스러워하는 부분이 바로 이것입니다.

이러한 비율은 10%에 도달하면 백그라운드 쓰기 저장이 시작되고 20%는 쓰기 저장 캐시의 최대 크기임을 의미합니다. 또한 후기입 캐싱에는 "I/O 없는 더티 제한"이 적용된다는 것을 알고 있습니다. 쓰기 저장 캐시가 15% 이상으로 증가하면 더티 페이지를 생성하기 위해 write()를 사용하는 프로세스가 "제한"됩니다. 즉, 커널은 write() 호출 내에서 프로세스를 휴면 상태로 만듭니다. 따라서 커널은 절전 기간을 제어하여 후기입 캐시의 크기를 제어할 수 있습니다. 참고로 이전 질문에 대한 답변을 참조하세요.

하지만 제가 관찰한 "비율"은 15% 제한 임계값보다 훨씬 낮은 것 같습니다. 내가 놓친 몇 가지 요소가 있어야합니다! 왜 이런 일이 발생합니까?

이전 테스트에서는 15~17.5% 정도의 값을 봤습니다.

내 커널은 Linux입니다 4.18.16-200.fc28.x86_64.

테스트는 다음과 같습니다. 나는 dd if=/dev/zero of=~/test bs=1M status=progress. 동시에 달성된 더러운 비율을 모니터링했습니다. dd15GB 이후에 명령을 중단했습니다.

$ while true; do grep -E '^(Dirty:|Writeback:|MemFree:|Cached:)' /proc/meminfo | tr '\n' ' '; echo; sleep 1; done
...
MemFree:          139852 kB Cached:          3443460 kB Dirty:            300240 kB Writeback:        135280 kB
MemFree:          145932 kB Cached:          3437220 kB Dirty:            319588 kB Writeback:        112080 kB
MemFree:          134324 kB Cached:          3448776 kB Dirty:            237612 kB Writeback:        160528 kB
MemFree:          134012 kB Cached:          3449004 kB Dirty:            169064 kB Writeback:        143256 kB
MemFree:          133760 kB Cached:          3449024 kB Dirty:            105484 kB Writeback:        119968 kB
MemFree:          133584 kB Cached:          3449032 kB Dirty:             49068 kB Writeback:        104412 kB
MemFree:          134712 kB Cached:          3449116 kB Dirty:                80 kB Writeback:         78740 kB
MemFree:          135448 kB Cached:          3449116 kB Dirty:                 8 kB Writeback:             0 kB

예를 들어 출력의 첫 번째 줄을 인용하려면 다음과 같이 하세요.

avail = 139852 + 3443460 = 3583312
dirty = 300240 + 135280 = 435520
ratio = 435520 / 3583312 = 0.122...

나는 그것을 제한하는 것을 하나 찾았지만 이러한 결과를 보기에는 충분하지 않았습니다. 나는 그것을 설정하려고 노력했습니다 /sys/class/bdi/*max_ratio. 질문의 테스트 결과는 max_ratio = 1로 실행한 결과입니다.

위 테스트를 반복하면 max_ratio = 100더 높은 더티 비율(예: 0.142)을 얻을 수 있습니다.

MemFree:   122936 kB Cached:   3012244 kB Dirty:     333224 kB Writeback: 13532 kB

쓰기 테스트는 이를 안정적으로 관찰하는 데 꽤 오랜 시간이 걸립니다(예: 8GB). 이 테스트에는 약 100초가 소요됩니다. 회전하는 하드 드라이브를 사용하고 있습니다.

4GB로 테스트를 시도했는데 더티 비율이 0.129에 불과했습니다.

MemFree:   118388 kB Cached:   2982720 kB Dirty:     249020 kB Writeback: 151556 kB

내가 말했듯이 이것은 나를 놀라게했습니다. 전문가 소스가 있어요2013년dd, 시스템이 더티 비율 0.15에 도달할 때까지 더티 페이지를 생성하려면 "자유 실행"해야 한다고 말합니다 . 그것 은 그것에 대해 명시 적으로 이야기 합니다 max_ratio.

답변1

MemFree"비율"은 + 의 백분율로 표시되는 더티 페이지 캐시(즉, 다시 쓰기 캐시)의 크기를 나타냅니다 Cached. 이는 MemTotal의 백분율이 아닙니다. 위의 질문에서 제가 혼란스러워한 부분이 바로 여기입니다.

아니요, 해당 설명은 아직 정확하지 않습니다.

Cachedtmpfs, 및 기타 배포판 Shmem의 모든 파일을 포함합니다 . 페이지 캐싱을 사용하여 구현되었기 때문에 계산됩니다. 그러나 이는 영구 저장소의 캐시가 아닙니다. 그냥 버릴 수는 없습니다. tmpfs페이지는 교환될 수 있지만 교환 가능한 페이지는 계산에 포함되지 않습니다.

나는 그 중 500-600MB를 가지고 있습니다 Shmem. 추적점을 다시 보려고 시도했을 때(이전 질문에 대한 답변 참조) 이것은 대략 적절한 양이었고 limit/0.20이 예상보다 낮은 이유를 설명할 것입니다.

또한 Cached제외 Buffers될 수 있습니다.일부 설정에서는 놀라울 정도로 많은 양이 발생함.

구현을 자세히 살펴봐야 한다고 생각했습니다.global_dirtyable_pages()내 커널 버전에서는 /proc/vmstat.

답변2

ext2/4에서는 5초마다 기본 새로 고침이 이루어지며 data=ordered이는 기본값이기도 합니다.

   commit=nrsec
          Start  a  journal  commit every nrsec seconds.  The default value is 5 seconds.  Zero means de-
          fault.

따라서 페이지가 더러워진 상태를 유지하고 싶지 않다면(또는 너무 오랫동안 더러워진 상태로 유지되는 경우) 가장 먼저 조정해야 할 곳은 바로 여기입니다.


여기에 딜레마가 있습니다. 몇 년 전 ext4 데이터 손실과 관련된 큰 문제입니다(참조:noauto_da_alloc설치 옵션):

커널은 필요한 경우에만 쓸 준비가 되어 있습니다. 따라서 크기와 기간 또는 제한을 기준으로 제한할 수 있습니다. VM은 기본 스토리지의 캐시 역할을 합니다.

"데스크톱" 사용자는 대부분 이 추가 레이어를 사용할 준비가 되어 있지 않습니다. 그가 할 때구하다파일을 제외하면 즉시 스토리지에 파일이 물리적으로 존재합니다. 이것이 vimfs 또는 fsync 옵션이 있는 이유입니다.

활성화되면 파일에 쓴 후 라이브러리 함수 fsync()가 호출됩니다. 이는 파일을 디스크에 플러시하여 메타데이터 로깅만 수행하는 파일 시스템에서도 안전하게 쓸 수 있도록 보장합니다. 이렇게 하면 노트북 모드로 실행되는 Linux 시스템에서 하드 드라이브가 강제로 회전하게 되므로 일부 경우에는 바람직하지 않을 수 있습니다.


git repo 작업에서 500,000개의 더티 페이지가 있었는데 background크기 제한에 도달하여 완전히 사라졌습니다. 또한 git이 repack/garbage collection을 결정하면 동기화하는 것처럼 보입니다 . vimset 과 비슷합니다 .fs

(다른 파티션의) 마운트도 동기화됩니다.

그러나 ext4 log의 길고 ratio긴 커밋 시간으로 인해 expire_centisecs5초도 없고 누구도(vim, git) 동기화되지 않습니다.RAM의 절반이 몇 시간 동안 더러워질 수 있습니다.

답변3

dd의 크기를 몇 페이지로 줄였습니다.

dd if=/dev/zero of=zerooo count=250 bs=4096

스크립트에는 중요한 매개변수가 표시됩니다.

grep dirty /proc/vmstat
grep ''    /proc/sys/vm/*centi*
grep ''    /proc/sys/vm/dirt*ratio

만료는 실제로 해제되어 있으며 임계값은 250dd 페이지보다 높습니다.

nr_dirty 0 
nr_dirty_threshold 2398                          
nr_dirty_background_threshold 1199
/proc/sys/vm/dirty_expire_centisecs:360000
/proc/sys/vm/dirty_writeback_centisecs:360000
/proc/sys/vm/dirty_background_ratio:0             
/proc/sys/vm/dirty_ratio:0

비율은 0이며 이는 절대 매개변수를 에코하고 있음을 나타냅니다.

/proc/sys/vm/dirty_background_bytes:9819200
/proc/sys/vm/dirty_bytes:9819200

선행 9는 819200바이트 = 200페이지를 약 1000페이지로 변환합니다. 위의 "임계값"을 참조하세요.

이제 설치 옵션이 중요합니다. 불행히도 "data=writeback"도 설치했는데 이로 인해 일부 새로 고침이 간접적으로 방해가 되었는지는 알 수 없습니다. 그러나 dd가 직접 더티 페이지만 생성하려면 noauto, 긴 커밋 및 "writeback"이 모두 필요한 것 같습니다.

TARGET       SOURCE    FSTYPE OPTIONS
/            /dev/sda3 ext4   rw,relatime,noauto_da_alloc,data=writeback
`-/mnt/sda/4 /dev/sda4 ext4   rw,relatime,noauto_da_alloc,commit=3600,data=writeback

지금:

$ time dd if=/dev/zero of=zerooo count=150 bs=4096
150+0 records in
150+0 records out
614400 bytes (614 kB, 600 KiB) copied, 0.00106973 s, 574 MB/s

real    0m0.003s
user    0m0.000s
sys     0m0.003s

오리지널 버전도 있습니다. 병렬로 실행할 스크립트:

Dirty:                 0 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:               600 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:     

0으로 내려가는 것이 제가 Zeroooo에서 한 일입니다. 유통기한이 길어서 여기까지 남아있어요.

뒤쪽에:

echo 25600 > /proc/sys/vm/dirty_bytes

임계값은 매우 작습니다. 배경 값은 자동으로 50%로 조정됩니다. :

nr_dirty 0
nr_dirty_threshold 7 
nr_dirty_background_threshold 3

이제 나는 다음을 얻습니다:

$ time dd if=/dev/zero of=zerooo count=150 bs=4096
150+0 records in
150+0 records out
614400 bytes (614 kB, 600 KiB) copied, 0.0258571 s, 23.8 MB/s

real    0m0.028s
user    0m0.003s
sys     0m0.000s

더 오래, 더 오래! 조절판! 그리고 남은 12kB의 더티 데이터만 있습니다.

Dirty:                 0 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 
Dirty:                12 kB Writeback:             0 kB 
Dirty:                12 kB Writeback:             0 kB 
Dirty:                12 kB Writeback:             0 kB 
Dirty:                12 kB Writeback:             0 kB 
... snip
Dirty:                12 kB Writeback:             0 kB 
Dirty:                12 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 

rm Zerooo는 nr_dirty를 다시 0으로 설정합니다.

DD#3:

상한은 150페이지보다 훨씬 높지만 배경은 여전히 ​​3개입니다.

nr_dirty 0
nr_dirty_threshold 2448
nr_dirty_background_threshold 3

dd가 최고 속도로 돌아왔습니다. dd는 이 페이지가 정확히 어디에 있는지 신경 쓰지 않습니다. 이미 작성되었습니다.

$ time dd if=/dev/zero of=zerooo count=150 bs=4096
150+0 records in
150+0 records out
614400 bytes (614 kB, 600 KiB) copied, 0.0011005 s, 558 MB/s

real    0m0.003s
user    0m0.003s
sys     0m0.000s

결과는 두 번째 실행과 유사합니다. 일부 kB는 "백그라운드"로 플러시되지 않지만 숫자가 더 낮기 때문에 아마도 인위적인 분수일 것입니다. 내 경험상 시작하면 "0"으로 플러시됩니다.

Dirty:                 0 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 
Dirty:                36 kB Writeback:             0 kB 
Dirty:                36 kB Writeback:             0 kB 
Dirty:                36 kB Writeback:             0 kB 
Dirty:                36 kB Writeback:             0 kB 
Dirty:                36 kB Writeback:             0 kB 
Dirty:                36 kB Writeback:             0 kB 
Dirty:                36 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 
Dirty:                 0 kB Writeback:             0 kB 

이제 다음과 같이 변경하세요.

mount -o remount,commit=13 /mnt/sda/4

배경이 150페이지를 초과하면(첫 번째 실행 참조) data=writeback을 사용해도 13초 후에 추가 더티 정보를 얻습니다.

 Dirty:                 0 kB  
 Dirty:                 0 kB  
 Dirty:                 0 kB  
 Dirty:               456 kB   ??? seems to appear always
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               600 kB  
 Dirty:               620 kB    !!! after 13 seconds commit= mount option
 Dirty:               620 kB  
 Dirty:               620 kB  
 Dirty:               620 kB  
 Dirty:               620 kB  
 Dirty:               620 kB  
 Dirty:               620 kB  
 Dirty:               620 kB  
 Dirty:               620 kB  
 Dirty:               620 kB    rm zeroooo
 Dirty:                20 kB  
 Dirty:                20 kB  
 Dirty:                20 kB  
 Dirty:                20 kB  
 Dirty:                20 kB  
 Dirty:                20 kB    sync
 Dirty:                 0 kB   

이 5초 데이터 및 메타데이터 패킷은 /proc/sys/vm/의 "centsecs" 매개변수에 의해 30초마다 새로 고쳐져야 합니다. 하지만 함께만. 이것이 data=ordered작용하는 곳 입니다 .

nr_dirty제목: 물론, ctrl-c dd를 누른 후 모니터링 스크립트를 시작하면 /proc/vmstat의 내용은 상한 임계값을 초과할 수 없습니다.

관련 정보