이러한 결과를 재현하는 방법 - 중요한 세부정보

이러한 결과를 재현하는 방법 - 중요한 세부정보
  1. sudo dd if=/dev/sda of=/dev/null bs=1M iflag=direct
  2. atopsar -d 5 # in a second terminal
  3. top # in a third terminal

왜냐하면. . . 결과 atopsar:

19:18:32  disk           busy read/s KB/read  writ/s KB/writ avque avserv _dsk_
...
19:16:50  sda             18%  156.5  1024.0     0.0     0.0   5.0   1.15 ms
19:16:55  sda             18%  156.3  1024.0     0.0     0.0   4.9   1.15 ms
...

보고된 디스크 사용률("사용 중")이 100%보다 훨씬 낮은 이유는 무엇입니까?

top해당 프로세스는 ddCPU의 3% 이하만 사용한다고 합니다 . 시스템 CPU의 하드웨어 및 소프트웨어 인터럽트(및) 사용량에 대한 전체 보고서도 제공되며 top1% 미만을 보여줍니다. 4개의 CPU(각각 2개의 스레드가 있는 2개의 코어)가 있습니다.hisi

/dev/sdaSATA 하드디스크 입니다. SSD도 아니고 하이브리드 SSHD 드라이브도 아닙니다. 읽기 속도는 초당 150MB를 초과할 수 없습니다 :-). 따라서 결과의 이 부분은 의미가 있습니다. 156 읽기/초 * 1024KB/읽기 = 156MB/초

커널 버전은 5.0.9-200.fc29.x86_64(Fedora Workstation 29)입니다. IO 스케줄러는 mq-deadline커널 버전 5.0부터 시작하여 다중 대기열 블록 계층을 사용합니다. 단일 대기열 블록 레이어가 제거되었기 때문입니다 :-).

디스크 사용률 수치는 다음 중 하나를 기준으로 계산 atopsar -d됩니다 .atop커널 iostat 필드. 링크된 문서에는 "필드 10 - I/O 수행에 소요된 밀리초 수"가 언급되어 있습니다. 더 자세한 정의가 있지만, 언급된 기능이 다중 대기열 블록 계층에 여전히 존재하는지 확실하지 않습니다. 내가 아는 한, atopsar -d둘 다 atop사용유니버셜 코드sar -diostat -x이 필드를 읽어보세요 10. ( // ​​이 필드 도 사용한다고 생각합니다 mxiostat.py)

추가 테스트

변형 2: 로 변경하되 bs=512k유지합니다 iflag=direct.

dd if=/dev/sda of=/dev/null bs=512k iflag=direct

19:18:32  disk           busy read/s KB/read  writ/s KB/writ avque avserv _dsk_
...
19:18:00  sda             35%  314.0   512.0     0.0     0.0   2.1   1.12 ms
19:18:05  sda             35%  313.6   512.0     0.2     4.0   2.1   1.11 ms

변형 3: 을 사용 bs=1M하지만 제거는 iflag=directdd10%의 CPU와 35%의 디스크를 사용합니다.

dd if=/dev/sda of=/dev/null bs=1M

19:18:32  disk           busy read/s KB/read  writ/s KB/writ avque avserv _dsk_
...
19:21:47  sda             35%  242.3   660.2     0.0     0.0   5.4   1.44 ms
19:21:52  sda             31%  232.3   667.8     0.0     0.0   9.5   1.33 ms

이러한 결과를 재현하는 방법 - 중요한 세부정보

실행되는 마지막 테스트를 참고하세요.dd 아니요 iflag=direct

좀 돼지같네요. 시스템(마우스 커서)이 10초 이상 정지되는 것을 본 적이 있습니다. 스왑을 비활성화하더라도. (RAM 채우기 테스트이득/캐시. 비활성 LRU 목록을 채우고 있습니다. 처리가 완료되면 캐시된 비활성 페이지가 상대적으로 빠르게 제거될 것이라고 생각합니다. 동시에 디스크는 순차 읽기로 인해 페이지를 처리해야 할 때 시간이 더 오래 걸립니다. 이 상황이 얼마나 나쁜지는 커널이 결국 활성 LRU 목록도 뒤집는지 아니면 너무 많이 축소하는지에 따라 달라질 수 있습니다. 즉, 현재 상황은 어떠한가?"최첨단 사례와 다양한 최적화를 포착하기 위해 일부 수정과 다양한 알고리즘의 혼합"귀하의 경우에는 작동합니다).

이것정밀한첫 번째 테스트 결과는 재현하기 어렵습니다.

때로는 대신 KB/read으로 표시됩니다 . 이 경우 다른 결과는 의 결과와 더 비슷해 보입니다 . 무엇보다도 디스크 사용률이 약 20%가 아닌 약 35%로 나타났습니다. 두 경우 모두 내 질문은 유효합니다.5121024bs=512k

이 동작을 이해하려면 여기를 참조하세요.내 IO 요청 크기가 약 512K로 제한되는 이유는 무엇입니까?

답변1

이는 커널 버전 5.0의 변경 결과입니다.

블록: part_round_stats를 제거하고덜 정확한 계산으로 전환

우리는 이것을 CPU당 in_flight 카운터로 변환하고 싶습니다.

part_round_stats 함수에는 각 jiffy에 대한 in_flight 카운터가 필요하며 jiffy당 모든 CPU 변수를 합산하는 비용이 너무 높으므로 제거해야 합니다. part_round_stats는 time_in_queue 및 io_ticks라는 두 개의 카운터를 계산하는 데 사용됩니다.

time_in_queue는 I/O 종료 시 I/O 지속 시간을 추가하여 part_round_stats 없이 계산할 수 있습니다. (이 값은 진행 중인 I/O의 시간이 계산되지 않는다는 점을 제외하면 이전에 계산된 값과 거의 동일합니다. ).

io_ticks는 I/O가 시작되거나 종료되고 jiffies 값이 변경될 때 값을 늘려 대략적으로 계산할 수 있습니다. I/O에 1초 미만이 소요되는 경우 이 값은 이전에 계산된 값만큼 정확합니다. I/O가 1초 이상 걸리는 경우 io_ticks는 이전에 계산된 값보다 뒤쳐질 수 있습니다.

( io_ticks을 위한부분 통계 표시(),공급커널 IO 통계"필드 10 - I/O 수행에 소요된 밀리초 수"의 경우. )

이것은 내 결과를 잘 설명합니다. Fedora 커널 구성에서 "순간"1ms입니다. 커밋하는 대규모 읽기 IO는 dd1~2초 이상 기다릴 수 있을 것으로 예상됩니다. 특히 오래된 기계식 HDD를 사용하는 시스템에서는 더욱 그렇습니다.

이전 커널 시리즈 4.20.x로 돌아가면 올바른 디스크 사용률이 표시됩니다.

$ uname -r
4.20.15-200.fc29.x86_64
$ atopsar -d 5
...
13:27:19  disk           busy read/s KB/read  writ/s KB/writ avque avserv _dsk_
13:28:49  sda             98%  149.4  1024.0    13.0     5.3   2.2   6.04 ms
13:28:54  sda             98%  146.0  1024.0     7.2     5.7   1.5   6.38 ms

cfq이 오래된 커널은 기본적으로 기존 단일 대기열 블록 계층과 IO 스케줄러를 사용합니다. IO 스케줄러를 사용할 때의 결과는 동일합니다 deadline.


업데이트: 커널 5.7부터 이 근사치가 조정되었습니다. 질문의 명령은 다시 디스크 사용률을 100%로 표시합니다. 좀 더 복잡한 워크로드에서는 새로운 근사치가 충돌할 것으로 예상됩니다(아직 눈치채지는 못했지만).

block/diskstats: 느린 디스크에 대한 io_ticks의 보다 정확한 근사치

현재 jiffies 카운터가 변경된 경우 io_ticks의 대략적인 값은 요청의 시작과 끝마다 1씩 증가합니다. 이는 1초보다 짧은 요청이나 1초마다 하나의 요청이 시작/종료되는 경우에 유용합니다.

디스크가 한 번에 하나의 요청만 수행하고 해당 요청이 2지피보다 긴 경우 첫 번째와 마지막 지피만 계산됩니다.

수정은 간단합니다. 요청이 끝나면 단 하나의 jiffy 대신 io_ticks에 대한 마지막 업데이트 이후 전달된 io_ticks jiffy를 추가합니다.

예: 일반 하드 디스크가 임의 읽기 4k 요청을 수행하는 데 걸리는 시간은 약 12ms입니다.

fio --name=test --filename=/dev/sdb --rw=randread --direct=1 --runtime=30 & iostat -x 10 sdb

패치 전후에 iostat의 "%util"이 8,43% -> 99,99%로 변경된 점에 유의하세요.

앞으로:

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sdb               0,00     0,00   82,60    0,00   330,40     0,00     8,00     0,96   12,09   12,09    0,00   1,02   8,43

뒤쪽에:

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sdb               0,00     0,00   82,50    0,00   330,00     0,00     8,00     1,00   12,10   12,10    0,00  12,12  99,99

이제 io_ticks는 요청의 시작과 끝 사이의 시간을 줄이지 않지만 대기열 깊이가 1보다 큰 경우 인접한 시작 사이의 일부 I/O 시간이 손실될 수 있습니다.

로드 추정의 경우 "%util"은 평균 대기열 길이만큼 유용하지는 않지만 디스크 대기열이 완전히 비어 있는 빈도를 명확하게 보여줍니다.

수정: 5b18b5a("차단: part_round_stats를 제거하고 덜 정확한 계산으로 전환")
승인: Konstantin Khlebnikov <[이메일 보호됨]>
검토자: 레이 밍<[이메일 보호됨]>
서명자: Jens Axboe <[이메일 보호됨]>

관련 정보