내 기본 가정은 프로세스에 대한 유일한 제한 요소가 디스크와 CPU일 때 전체 시스템 "iowait" + CPU 사용량이 적어도 하나의 논리적 CPU의 100%와 같아야 한다는 것입니다. (이것이 사실이 아닌 다른 상황도 있습니다. 예를 들어, 다운로드한 파일을 사용할 때 wget
네트워크가 제한 요소인 경우가 많습니다.)
간단한 테스트는 이 가정을 위반합니다. 이것이 예상되는가? 그것이 예상된다면, 내가 할 수 있는 일련의 조건이 있습니까?~해야 한다나는 내 가설이 사실일 것으로 기대하는가?
"iowait"에 대한 배경 정보는 다음과 같습니다.CPU는 IO가 보류 중인지 어떻게 알 수 있나요? 여기에 대한 답변은 누적된 iowait가 "특정 조건에서 감소될 수 있다"는 반직관적인 아이디어를 인용합니다. 내 간단한 테스트가 문서화되지 않은 상황을 유발할 수 있는지 궁금합니다.
고쳐 쓰다: 제발답변으로 건너뛰기.
대답은 내가 원래 사용한 것보다 더 간단한 테스트입니다. 아래에 원래 질문을 유지했습니다. 원래 질문에는 몇 가지 추가 세부정보가 표시될 수 있습니다.
원래 질문
짧은 테스트에서 나는 dd
커널에게 임의의 바이트를 생성하고 이를 파일에 쓰도록 요청하곤 했습니다. 커널에서 소비된 CPU 시간을 계산하기 위해 dd
내부에서 명령을 실행했습니다 . perf stat
나는 또한 내부를 실행 perf trace -s
하고 내부에서 보낸 시간을보고했습니다 write()
. 동시에 vmstat 5
다른 터미널을 실행하여 "iowait" 시스템을 확인했습니다.
- 나는 최소한 전체 CPU가 "유휴 상태가 아닌" 상태, 즉 100% 실행 중이거나 중지되었지만 IO("iowait" 상태)를 기다리고 있는 상태를 볼 것으로 예상합니다. 아니요.
- (또한 "iowait" 시간이 write()에 소요된 시간과 대략 일치할 것으로 예상했지만 그렇지 않은 것 같습니다.)
자세한 결과와 테스트 환경은 아래와 같습니다. 또한 내 가설이 뒷받침되는 또 다른 테스트도 표시됩니다. 참고: perf stat
내부에서 실행 해야 하며 perf trace
반대 방향으로 실행해서는 안 됩니다. 세부사항은 다음과 같습니다:"성능 추적 -s"를 실행할 때 "성능 통계"(및 "시간"!)가 잘못된 결과를 표시합니까?
"iowait"에 대한 배경 정보
맨페이지에서 가져온 정의는 다음과 같습니다
sar
.%io는 다음을 기다립니다:
시스템에 미해결 디스크 I/O 요청이 있는 동안 하나 이상의 CPU가 유휴 상태였던 시간의 비율입니다.
따라서 %iowait는 CPU 관점에서 실행할 작업이 없지만 적어도 하나의 I/O가 진행 중임을 의미합니다. iowait는 단지 자유 시간일 뿐이며 어떤 것도 예약할 수 없습니다. 이 값은 성능 문제를 나타내는 데 유용할 수도 있고 그렇지 않을 수도 있지만 사용자에게 시스템이 유휴 상태이고 추가 작업이 필요할 수 있음을 알려줍니다.
https://support.hpe.com/hpsc/doc/public/display?docId=c02783994
더 긴 기사도 있습니다:I/O 대기 이해(또는 0% 유휴 상태가 좋은 이유). 이는 커널 코드에서 정의를 명확하게 볼 수 있는 방법을 설명합니다. 코드는 약간 변경되었지만 아이디어는 여전히 명확합니다.
/*
* Account for idle time.
* @cputime: the CPU time spent in idle wait
*/
void account_idle_time(u64 cputime)
{
u64 *cpustat = kcpustat_this_cpu->cpustat;
struct rq *rq = this_rq();
if (atomic_read(&rq->nr_iowait) > 0)
cpustat[CPUTIME_IOWAIT] += cputime;
else
cpustat[CPUTIME_IDLE] += cputime;
}
이 기사에서는 단일 CPU 시스템에 대한 몇 가지 관련 실험도 보여줍니다. 일부 실험에서는 ! dd
을 사용하기도 했습니다 if=/dev/urandom
. 그러나 실험에는 내 테스트가 포함되지 않았습니다 dd if=/dev/urandom of=test.out
. .dd if=/dev/urandom of=/dev/null
"IO 대기"에 대해 생각하는 것은 다중 CPU 시스템을 사용하기 때문에 지금은 약간 까다롭지만 참조된 코드를 보면 여전히 이해하고 있다고 생각합니다.
환경
논리 CPU가 4개 있습니다.
LVM과 ext4 파일 시스템을 사용합니다. 디스크나 파일 시스템에 암호화를 사용하지 않습니다. 네트워크 파일 시스템이 전혀 마운트되어 있지 않으므로 네트워크 파일 시스템에서 읽거나 쓰지 않습니다.
아래 결과는 IO 스케줄러를 4.20.15-200.fc29.x86_64
사용하여 커널에서 가져온 것입니다 . noop
IO 스케줄러 cfq
도 비슷한 결과를 제공했습니다.
( 유사한 구성을 기반으로 하지만 커널 버전 5.1에 더 가깝고 mq-deadline
.blk-mq
테스트 및 결과
$ sudo perf trace -s \
perf stat \
dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000
3000+0 records in
3000+0 records out
3145728000 bytes (3.1 GB, 2.9 GiB) copied, 31.397 s, 100 MB/s
Performance counter stats for 'dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000':
18,014.26 msec task-clock # 0.574 CPUs utilized
3,199 context-switches # 0.178 K/sec
4 cpu-migrations # 0.000 K/sec
328 page-faults # 0.018 K/sec
45,232,163,658 cycles # 2.511 GHz
74,538,278,379 instructions # 1.65 insn per cycle
4,372,725,344 branches # 242.737 M/sec
4,650,429 branch-misses # 0.11% of all branches
31.398466725 seconds time elapsed
0.006966000 seconds user
17.910332000 seconds sys
Summary of events:
...
dd (4620), 12156 events, 12.0%
syscall calls total min avg max stddev
(msec) (msec) (msec) (msec) (%)
--------------- -------- --------- --------- --------- --------- ------
read 3007 17624.985 0.002 5.861 12.345 0.21%
write 3003 13722.837 0.004 4.570 179.928 2.63%
openat 12 0.371 0.002 0.031 0.267 70.36%
...
iowait
나는 칼럼에서 이 숫자를 읽었습니다 . 열(= 1K 출력 블록)을 보면 테스트가 실행 중인 시기를 알 수 있습니다.wa
vmstat
io
bo
$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 5126892 176512 1486060 0 0 1788 4072 321 414 4 4 83 9 0
1 0 0 5126632 176520 1485988 0 0 0 7 212 405 0 1 99 0 0
0 0 0 5126884 176520 1485988 0 0 0 0 130 283 0 0 99 0 0
0 0 0 5126948 176520 1485908 0 0 0 1 157 325 0 0 99 0 0
0 0 0 5126412 176520 1486412 0 0 115 0 141 284 0 0 99 0 0
0 2 0 5115724 176548 1487056 0 0 0 6019 18737 10733 3 6 89 2 0
1 0 0 5115708 176580 1487104 0 0 3 91840 1276 990 0 13 77 9 0
1 0 0 5115204 176600 1487128 0 0 2 91382 1382 1014 0 14 81 4 0
1 0 0 5115268 176636 1487084 0 0 4 88281 1257 901 0 14 83 3 0
0 1 0 5113504 177028 1487764 0 0 77 92596 1374 1111 0 15 83 2 0
1 0 0 5114008 177036 1487768 0 0 0 113282 1460 1060 0 16 81 2 0
1 0 0 5113472 177044 1487792 0 0 0 110821 1489 1118 0 16 74 10 0
0 0 0 5123852 177068 1487896 0 0 0 20537 631 714 1 3 94 2 0
0 0 0 5123852 177076 1487856 0 0 0 10 324 529 2 1 98 0 0
2 0 0 5123852 177084 1487872 0 0 0 70 150 299 0 0 99 0 0
테스트 결과(가상머신 내부)
커널을 실행하고 (그래서 blk-mq를 5.0.9-301.fc30.x86_64
사용하는 ) 1개의 CPU가 있는 VM에서 동일한 테스트를 시도했습니다 . mq-deadline
이번 테스트에서는 예상대로 작동했습니다.
$ sudo perf trace -s \
perf stat \
dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000
[sudo] password for alan-sysop:
3000+0 records in
3000+0 records out
3145728000 bytes (3.1 GB, 2.9 GiB) copied, 46.8071 s, 67.2 MB/s
Performance counter stats for 'dd if=/dev/urandom of=test.out bs=1M oflag=direct count=3000':
18,734.89 msec task-clock # 0.400 CPUs utilized
16,690 context-switches # 0.891 K/sec
0 cpu-migrations # 0.000 K/sec
328 page-faults # 0.018 K/sec
<not supported> cycles
<not supported> instructions
<not supported> branches
<not supported> branch-misses
46.820355993 seconds time elapsed
0.011840000 seconds user
18.531449000 seconds sys
Summary of events:
...
dd (1492), 12156 events, 38.4%
syscall calls total min avg max stddev
(msec) (msec) (msec) (msec) (%)
--------------- -------- --------- --------- --------- --------- ------
write 3003 28269.070 0.019 9.414 5764.657 22.39%
read 3007 18371.469 0.013 6.110 14.848 0.53%
execve 6 10.399 0.012 1.733 10.328 99.18%
...
출력 vmstat 5
:
$ vmstat 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 726176 52128 498508 0 0 2040 231 236 731 7 5 77 11 0
0 0 0 726176 52136 498508 0 0 0 10 25 46 0 0 99 1 0
0 0 0 726208 52136 498508 0 0 0 0 29 56 0 0 100 0 0
0 1 0 702280 55944 511780 0 0 2260 13109 4399 9049 3 17 55 25 0
0 1 0 701776 56040 511960 0 0 18 129582 1406 1458 0 73 0 27 0
0 2 0 701524 56156 512168 0 0 22 87060 960 991 0 50 0 50 0
3 1 0 701524 56228 512328 0 0 14 118170 1301 1322 0 68 0 32 0
1 1 0 701272 56260 512392 0 0 6 86426 994 982 0 53 0 46 0
0 2 0 701020 56292 512456 0 0 6 56115 683 660 0 37 0 63 0
3 2 0 700540 56316 512504 0 0 5 33450 446 457 0 26 0 74 0
0 2 0 700860 56332 512536 0 0 3 16998 311 240 0 19 0 81 0
1 2 0 700668 56368 512616 0 0 7 32563 443 428 0 24 0 76 0
1 0 0 700668 56392 512648 0 0 3 20338 245 272 0 12 0 88 0
0 1 0 707096 56408 512920 0 0 54 20913 312 530 0 12 79 8 0
0 0 0 707064 56432 512920 0 0 0 49 39 64 0 0 45 55 0
0 0 0 707064 56432 512920 0 0 0 0 24 46 0 0 100 0 0
0 0 0 707064 56432 512920 0 0 0 80 28 47 0 0 100 0 0
VM에 CPU를 핫 추가해 보고 다시 테스트했습니다. 결과는 다양합니다. 유휴 열에 약 0%가 표시되는 경우도 있고 약 50%(즉, 두 CPU 중 하나)가 표시되는 경우도 있습니다. 0% "idle"에서는 "iowait"가 매우 높습니다. 즉, CPU 값이 두 개 이상입니다. 즉, 제가 예상한 2번 항목이 틀렸습니다. 도저히 받아들일 수 없어이것다중 CPU 시스템에서 "iowait"의 명백한 제한 사항. (그래도 잘 이해가 안 되네요. 누군가가 정확하게 설명해주고 싶다면 좋을 것 같습니다.) 그러나 두 경우 모두 "idle"이 50%를 초과하지 않으므로 이러한 테스트는 "iowait"에 대한 나의 첫 번째 가설과 여전히 일치합니다.
가상 머신을 종료한 다음 4개의 CPU로 시작해 보았습니다. 마찬가지로 유휴 상태는 정확히 75%로 표시되는 경우가 많으며 때로는 50%까지 낮기도 하지만 유휴 상태는 75% 이상(예: CPU 4개 중 3개 이상) 표시되지 않습니다.
4개의 CPU가 있는 물리적 시스템에서는 위에 표시된 80% 유휴 결과를 여전히 재현할 수 있습니다.
답변1
콘텐츠 알림: 이 문서에는 다양한 Linux 토론 및 코드에 대한 링크가 포함되어 있습니다. 일부 링크된 콘텐츠가 현행 행동강령을 준수하지 않습니다.스택 교환또는리눅스. 대부분 그들은 "[사람이 아닌] 코드를 모욕합니다." 사용된 언어에 관계없이 반복해서는 안 됩니다. 그러한 언어를 모방하거나 앵무새처럼 흉내내거나 논쟁을 벌이는 일을 삼가해 주시기 바랍니다.
Re: iowait가 유휴 계정과 "일관되지 않음" - iowait가 너무 낮음
2019년 5월 7일 12:38에 Peter Zijlstra는 다음과 같이 썼습니다.
2019년 7월 5일 금요일 오후 12시 25분 46초 +0100에 Alan Jenkins가 다음과 같이 썼습니다.
내 CPU "iowait" 시간이 잘못 보고된 것 같습니다. 왜 이런 일이 일어나는지 아십니까?
iowait는 마법의 난수이고 의미가 없기 때문입니다. 개인적으로 저는 이 부분을 제외하고는 전부 삭제하고 싶습니다.ABI:/
주변 리뷰도 확인하세요nr_iowait()
감사해요. [현재 문서에 언급된 문제]는 다른 질문이라고 생각하지만, 내 문제를 "해결"하기 위한 요구 사항(또는 포인트)이 많지 않다는 뜻입니다.
내 문제를 발견했습니다. 이 문제는 5년 전에 알려졌는데 이를 고치는 것은 쉬운 일이 아니다.
"iowait" 시간은 다음 함수에 의해 업데이트됩니다 account_idle_time()
.
/*
* Account for idle time.
* @cputime: the CPU time spent in idle wait
*/
void account_idle_time(u64 cputime)
{
u64 *cpustat = kcpustat_this_cpu->cpustat;
struct rq *rq = this_rq();
if (atomic_read(&rq->nr_iowait) > 0)
cpustat[CPUTIME_IOWAIT] += cputime;
else
cpustat[CPUTIME_IDLE] += cputime;
}
이것은 내가 기대했던 대로 작동합니다.대략적인 CPU 시간"샘플링"은 전통적인 타이머 인터럽트("틱")를 사용하여 수행됩니다. 단, 절전을 위해 유휴 시간 동안 체크를 꺼두면 작동하지 않을 수 있습니다 NO_HZ_IDLE
. 성능상의 이유로 틱을 끄도록 허용하는 경우에도 실패할 수 있습니다. NO_HZ_FULL
부팅이 필요하기 때문입니다.VIRT_CPU_ACCOUNTING
. 대부분의 Linux 커널은 절전 기능을 사용합니다. 일부 임베디드 시스템에서는 이 두 가지 기능을 사용하지 않습니다. 내 설명은 다음과 같습니다.
IO가 완료되면 장치는방해하다. 커널 인터럽트 핸들러는 다음을 사용하여 프로세스를 깨웁니다.try_to_wake_up()
. 카운터를 1씩 감소시킵니다 nr_iowait
.
if (p->in_iowait) {
delayacct_blkio_end(p);
atomic_dec(&task_rq(p)->nr_iowait);
}
프로세스가 유휴 CPU에서 깨어나는 경우 해당 CPU는 account_idle_time()
애플리케이션 구성에 따라 tick_nohz_account_idle_ticks()
에서 __tick_nohz_idle_restart_tick()
또는 vtime_task_switch()
에서 호출됩니다 finish_task_switch()
.
이때는 ->nr_iowait
축소되었습니다. 0으로 줄이면 iowait 시간이 기록되지 않습니다.
이 효과는 다양할 수 있습니다. 즉, 프로세스가 깨어난 CPU에 따라 다릅니다. IO 완료 인터럽트를 수신하는 동일한 CPU에서 프로세스가 깨어나는 경우 ->nr_iowait
유휴 시간이 줄어들기 전에 더 일찍 계산될 수 있습니다. 내 경우에는 CPU 0이 처리된 것으로 나타났습니다.아치을 보고 중단합니다 watch cat /proc/interrupts
.
간단한 순차 읽기로 이것을 테스트했습니다.
dd if=largefile iflag=direct bs=1M of=/dev/null
명령을 CPU 0 에 고정하면 taskset -c 0 ...
iowait에 대한 "올바른" 값이 표시됩니다. 다른 CPU에 고정하면 더 낮은 값이 표시됩니다. 명령을 정상적으로 실행하면 커널 버전 간에 변경된 스케줄러 동작에 따라 변경됩니다. 최근 커널(4.17, 5.1, 5.2-rc5-ish)에서는 "iowait" 시간이 이 부분으로 줄어들기 때문에 이 명령은 CPU 0에서 시간의 약 1/4이 걸리는 것으로 보입니다.
(설명되지 않음: 이제 내 가상 머신에서 이 테스트를 실행하면 각(또는 모든) CPU에 대해 "올바른" iowait가 재현되는 것처럼 보입니다. 이것이 관련되었을 수 있다고 생각됩니다.IRQ_TIME_ACCOUNTING
, 이 기능은 가상 머신 외부 테스트에도 사용되었습니다.
NO_HZ_IDLE
억제하면 4.17+에서는 CPU당 "올바른" iowait가 제공되지만 4.16 또는 4.15에서는 제공되지 않는 이유를 정확히 확인하지 못했습니다 .
내 가상 머신에서 이 테스트를 실행하면 각 CPU에 대해 "올바른" iowait가 재현되는 것 같습니다. 이 때문입니다 IRQ_TIME_ACCOUNTING
. VM 외부 테스트에도 사용되지만 VM 내부에서 테스트할 때 더 많은 중단이 발생합니다. 특히 "dd"가 실행 중인 가상 CPU에는 초당 1000개가 넘는 "함수 호출 인터럽트"가 있습니다.
그러니 제 설명의 세부사항에 너무 의존하시면 안 됩니다 :-)
"iowait"에 대한 배경 정보는 다음과 같습니다.CPU는 IO가 보류 중인지 어떻게 알 수 있나요? 여기에 대한 답변은 누적된 iowait가 "특정 조건에서 감소될 수 있다"는 반직관적인 아이디어를 인용합니다. 내 간단한 테스트가 문서화되지 않은 상황을 유발할 수 있는지 궁금합니다.
예.
처음 이 내용을 검색했을 때 "딸꾹질"이라는 용어를 발견했습니다. 또한 누적된 "iowait" 시간이 단조롭지 않음을 보여줌으로써 문제를 설명합니다. 즉, 뒤로 점프(감소)하는 경우도 있습니다. 위의 테스트만큼 간단하지는 않습니다.
그러나 조사를 해보니 동일한 근본적인 문제가 발견되었습니다. Peter Zijlstra와 Hidetoshi Seto는 각각 솔루션을 제안하고 프로토타입을 제작했습니다. 이 문제는 표지 메시지에 설명되어 있습니다.
[RFC 패치 0/8] iowait 회계 재작업(2014-07-07)
그 외에는 진전이 있다는 증거를 찾지 못했습니다. 세부 사항 중 하나에 답이 없는 질문이 있습니다. 또한 전체 시리즈는 PowerPC, S390 및 IA64 CPU 아키텍처에 대한 특정 코드를 다룹니다. 그래서 이 문제를 해결하는 것이 쉽지 않다고 말씀드리고 싶습니다.