Моє основне припущення полягає в тому, що коли лише обмежуючими факторами процесу є диск і процесор, то загальна система "iowait" + використання процесора повинна дорівнювати щонайменше 100% одного логічного процесора. (В інших випадках це не буде wgetдотримано . Наприклад, при завантаженні файлу за допомогою мережі часто є обмежуючим фактором).
Це припущення порушено простим тестом. Це очікується? Якщо очікується, чи існує ряд умов, коли я повинен очікувати, що моє припущення справдиться?
Тут є деякі відомості про "iowait": Як CPU знає, що IO очікує на розгляд? Тут відповідь цитує контр-інтуїтивну думку, що накопичувальне іоїти "може зменшитися за певних умов". Цікаво, чи може мій простий тест викликати такий незадокументований стан?
ОНОВЛЕННЯ : Перейдіть до відповіді .
У відповіді є більш простий тест, ніж той, який я використовував спочатку. Я зберегла початкове запитання нижче. Оригінальне запитання може містити деякі додаткові деталі.
Оригінальне запитання
У короткому тесті я використовую ddзапит ядра на створення випадкових байтів і записую їх у файл. Я запускаю ddкоманду всередині perf stat, просто щоб отримати підрахунок часу процесора, проведеного всередині ядра. Я також запускаю його всередину perf trace -s, щоб повідомити про час, проведений всередині write(). Одночасно біжу vmstat 5в інший термінал, щоб побачити систему "iowait".
- Я очікував, що побачу хоча б один цілий процесор як "непрацюючий", тобто 100% часу він або працює, або зупиняється, але чекає IO (стан "iowait"). Це не так.
- (Також я очікував, що час "iowait" приблизно відповідає часу, витраченому на запис (). Але, схоже, це не робилося.)
Детальні результати та середовище тестування показані нижче. Також показаний альтернативний тест, де моє припущення справдилося. Примітка: потрібно було бігати perf statвсередину perf trace, а не навпаки. Це детально тут: Чи показує "perf stat" (та "time"!) Неправильні результати при запуску "perf trace - s"?
Довідкова інформація про "iowait"
Далі йдеться з визначення, взятого на сторінці сторінки
sar:% iowait:
Відсоток часу, коли ЦП або ЦП були непрацюючими, протягом яких система мала непогашений запит вводу / виводу диска.
Тому% iowait означає, що з точки зору процесора жодні завдання не можна було виконати, але принаймні один введення / виведення виконується. iowait - це просто форма простою, коли нічого не можна було запланувати. Значення може бути або не корисним для вказівки на проблеми з продуктивністю, але воно вказує користувачеві, що система в режимі очікування та може зайняти більше роботи.
https://support.hpe.com/hpsc/doc/public/display?docId=c02783994
Є ще довша стаття: Розуміння очікування вводу / виводу (або чому 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;
}
У статті також показаний ряд пов'язаних експериментів над системою з одним процесором. Деякі з експериментів , навіть використовувати ddз if=/dev/urandom ! Однак експерименти не включають мій тест dd if=/dev/urandom of=test.out . Він тільки використовує dd if=/dev/urandom of=/dev/null .
"IO wait" трохи складніше думати про це зараз, оскільки ми використовуємо багатопроцесорні системи, але, думаю, я все-таки це розумію, виходячи з цитованого коду.
Навколишнє середовище
У мене є чотири логічні процесори.
Я використовую LVM та файлову систему ext4. Я не використовую жодного шифрування на своєму диску чи файловій системі. У мене взагалі не встановлена мережева файлова система, тому я не читаю і не записую мережеву файлову систему.
Нижче наведені результати з ядра 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рисунок із waстовпця vmstat. Ви можете сказати, коли тест працює, переглянувши ioстовпчик ( bo= 1 К блоків виводу).
$ 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
Результати тестування там, де він утримується (всередині VM)
Я спробував той самий тест всередині VM з 1 процесором, на якому було запущено ядро 5.0.9-301.fc30.x86_64і використовувалося mq-deadline(а значить, blk-mq). У цьому тесті він працював так, як я цього очікував.
$ 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 і тестувати ще раз. Результати були мінливими: іноді він показував близько 0% у режимі очікування, а іноді - близько 50% в режимі очікування (тобто один із двох процесорів). У випадку 0% "простою", "iowait" був дуже високим, тобто вартості більше одного процесора. Тобто, моє сподівання, пункт 2 був невірним. Я можу з грубою думкою прийняти це очевидне обмеження "iowait" на багатопроцесорних системах. (Хоча я не зовсім це розумію. Якщо хтось хоче це точно пояснити, це було б чудово). Однак в будь-якому випадку "простої" не перевищували 50%, тому ці тести все ще відповідали моєму першому припущенню про "iowait".
Я спробував вимкнути VM і запустити його з 4 процесорів. Аналогічно, часто я мав рівно 75% холостого ходу, а іноді я мав менше 50% в режимі очікування, але я не бачив більше 75% в режимі очікування (тобто більше трьох з чотирьох процесорів).
Якщо у фізичній системі з 4 процесорами я все одно можу відтворити результат більш ніж 80% в режимі очікування, як показано вище.
this_rq()->nr_iowaitце кількість завдань, які чекають на використання io_schedule() лише в поточному процесорі . Я помиляюся?
iowaitнамагається взагалі виміряти час, витрачений на очікування вводу-виводу. Це не відстежується конкретним процесором, і не може бути" . Дозвольте наголосити, що я не впевнений у цьому, просто висловлюючи здивування.
atop, або atopsar -c 5ви побачите цифри використання кожного процесора. Вони включають iowait, і показники iowait на CPU можуть показувати різні, ненульові значення :-). Або sar -P ALL 1, якщо ви не використовуєте atop. Це так, як iowaitмодель була розширена для багатопроцесорних систем ... Чого мені незрозуміло, чи є ця модель насправді придатною для використання, чи це спосіб, який дозволяє коду iowait продовжувати працювати, коли є лише один процесор? он-лайн, але інакше просто не заслуговує на довіру.