Ось як має поводитись пейджінг Linux?


26

Коли моя система Linux наближається до підкачки (тобто, в моєму випадку, 16 ГБ оперативної пам’яті майже повністю, 16 Гб своп повністю порожній), якщо новий процес X намагається виділити деяку пам’ять, система повністю блокується. Тобто, поки не буде замінена непропорційна кількість сторінок (wrt загальний розмір і швидкість запитів на розподіл пам'яті X). Зауважте, що не тільки gui стає абсолютно невідповідальним, але навіть основні сервіси, такі як sshd, повністю заблоковані.

Це два фрагменти коду (правда, грубий), який я використовую, щоб викликати цю поведінку більш "науково". Перший отримує два числа x, y з командного рядка і продовжує виділяти та ініціалізувати кілька фрагментів y байтів, поки не буде виділено більше x загальних байтів. А потім просто спить нескінченно. Це буде використано для виведення системи на межі підкачки.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main(int argc, char** argv) {
   long int max = -1;
   int mb = 0;
   long int size = 0;
   long int total = 0;
   char* buffer;

   if(argc > 1)
     {
       max = atol(argv[1]);
       size = atol(argv[2]);
     }
   printf("Max: %lu bytes\n", max);
   while((buffer=malloc(size)) != NULL && total < max) {
       memset(buffer, 0, size);
       mb++;
       total=mb*size;
       printf("Allocated %lu bytes\n", total);       
   }      
   sleep(3000000);
   return 0;
}

Другий фрагмент коду робить саме те, що робить перший, за винятком того, що він має sleep(1);право після printf(я не збираюся повторювати весь код). Цей буде використовуватися, коли система знаходиться на межі підкачки, щоб змусити її обмінюватися сторінками "щадним" способом, тобто повільно вимагати виділення нових шматочків пам'яті (так що система, безумовно, повинна мати можливість замінювати сторінки і бути в курсі нових запитів).

Отже, склавши два фрагменти коду, давайте назвемо відповідний exe fasteater та sloweater, зробимо це:

1) запускайте улюблені гуї (звичайно не обов'язково)

2) запустити метр мем / своп (наприклад watch -n 1 free)

3) запускати декілька випадків, fasteater x yколи х є порядком гігабайт, а y - порядком мегабайт. Робіть це, поки ви майже не заповніть барана.

4) запустити один екземпляр sloweater x y, знову ж таки, коли x є порядком гігабайт, а y - порядком мегабайт.

Після кроку 4) те, що повинно відбутися (і це завжди трапляється для моєї системи), це те, що після вичерпання оперативної пам'яті система повністю заблокується. gui заблоковано sshd заблоковано тощо. Але, але не назавжди! Після того, як sloweater закінчив запити на розподіл, система повернеться до життя (через хвилини блокування, а не секунди ...) у цій ситуації:

а) баран приблизно повний

б) swap також майже повний (пам'ятайте, він був порожній на початку)

в) жодного втручання вбивці.

І зауважте, що розділ swap знаходиться на SSD. Таким чином, система, здається, не в змозі поступово переміщувати сторінки від оперативної пам’яті до swap (імовірно, від застібок, які просто сплять), щоб створити місце для повільних (і лише декількох мегабайт) запитів повільного моменту.

Зараз хтось мене виправить, якщо я помиляюся, але це не здається так, як повинна вести себе сучасна система в таких умовах. Здається, він веде себе як старі системи (назад назад), коли не було підтримки пейджингу, а система віртуальної пам'яті просто замінила весь простір пам'яті деякого процесу замість кількох сторінок.

Може хтось теж це перевірить? І, можливо, хтось, у кого також є система BSD.

ОНОВЛЕННЯ 1 Я дотримувався рекомендацій Марка Плотника нижче в коментарях, і я почав, vmstat 1 >outперш ніж приступати до тестування підкачки. Результат ви можете побачити нижче (я вирізав всю початкову частину, де заповнюється баран без участі в свопі):

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   6144 160792      8 272868    0    0     0     0  281 1839  1  0 99  0  0
0  0   6144 177844      8 246096    0    0     0     0  425 2300  1  1 99  0  0
0  0   6144 168528      8 246112    0    0    16     0  293 1939  1  0 99  0  0
0  0   6144 158320      8 246116    0    0     0     0  261 1245  0  0 100  0  0
2  0  10752 161624      8 229024    0 4820 17148  4820  845 3656  1  2 97  0  0
2  0  10752 157300      8 228096    0    0 88348     0 2114 8902  0  5 94  1  0
0  0  10752 176108      8 200052    0    0 108312     0 2466 9772  1  5 91  3  0
0  0  10752 170040      8 196780    0    0 17380     0  507 1895  0  1 99  0  0
0 10  10752 160436      8 191244    0    0 346872    20 4184 17274  1  9 64 26  0
0 29 12033856 152888      8 116696 5992 15916880 1074132 15925816 819374 2473643  0 94  0  6  0
3 21 12031552 295644      8 136536 1188    0 11348     0 1362 3913  0  1 10 89  0
0 11 12030528 394072      8 151000 2016    0 17304     0  907 2867  0  1 13 86  0
0 11 12030016 485252      8 158528  708    0  7472     0  566 1680  0  1 23 77  0
0 11 12029248 605820      8 159608  900    0  2024     0  371 1289  0  0 31 69  0
0 11 12028992 725344      8 160472 1076    0  1204     0  387 1381  0  1 33 66  0
0 12 12028480 842276      8 162056  724    0  3112     0  357 1142  0  1 38 61  0
0 13 12027968 937828      8 162652  776    0  1312     0  363 1191  0  1 31 68  0
0  9 12027456 1085672      8 163260  656    0  1520     0  439 1497  0  0 30 69  0
0 10 12027200 1207624      8 163684  728    0   992     0  411 1268  0  0 42 58  0
0  9 12026688 1331492      8 164740  600    0  1732     0  392 1203  0  0 36 64  0
0  9 12026432 1458312      8 166020  628    0  1644     0  366 1176  0  0 33 66  0

Як ви бачите, як тільки заміна вмикається, відбувається масштабний обмін 15916880 Кбайт усі, який, я думаю, триває протягом усієї тривалості заморожування системи. І все це, мабуть, викликано процесом (повільнішим), який просто просить 10МБ щосекунди.

ОНОВЛЕННЯ 2: Я зробив швидку інсталяцію FreeBSD і повторив ту саму схему розподілу, що використовується з Linux ... і вона була такою ж гладкою, як і повинна бути. FreeBSD міняв сторінки поступово, в той час як повільний графік виділяв усі свої 10 МБ фрагментів пам'яті. Тут немає жодної сучки ... WTF відбувається тут ?!

ОНОВЛЕННЯ 3: Я подав помилку з помилкою ядра. Здається, привертає деяку увагу, так що ... пальці схрестили ...


2
Як я вже згадував, все заблоковано. Я спробував ssh'ing з іншої системи, це просто раз.
Джон Террагон

2
Якщо я запускаю vmstat 1 з виведенням stdout, я думаю, що він замерзне. Але ти маєш рацію, я міг би просто почати vmstat 1>somefileз системи, а потім побачити, про що вона повідомляє, після того, як система відновиться. Я спробую це.
Джон Террагон

2
Я використовував vmstat. Результати в оновленому вище.
Джон Террагон

3
swappinessє 60 за замовчуванням (не те, що його зміна дає кращий результат). Ядро, яке використовується під час vmstatвиконання, - 4.14.35, але я спробував 4.15, 4.16 і навіть повернувся до серії 4.0 (!): Завжди однакова поведінка. І це не те, що я використовую якийсь дивний розподіл, це просто debian. Я не використовую зображення ядра від debian (не те, що у мене є незвичайні конфігурації), але я спробував одне з таких ... те саме поведінку.
Джон Террагон

2
Дуже цікава дискусія про помилку ядра! І схоже, ви вирішили цю проблему, щоб замінити розділ, зашифрований LUKS. Можливо, ви захочете відредагувати свою відповідь або, можливо, опублікувати відповідь самостійно (з відомими досі обхідними шляхами, і, можливо, продовжувати оновлювати її, оскільки дискусія LKML досягає більш переконливих результатів.) Дуже вражає бачити спільноту ядер Linux на роботі! 😁
filbranden

Відповіді:


1

Саме для цього існує захист від треш .

Він постійно стежить за станом обміну і, коли щось випадково починає займати багато оперативної пам’яті, тимчасово заморожує жадібні оперативні процеси, тому ядро ​​має час для заміни деякої пам’яті, не роблячи всю систему невідповідною.


-3

Ви виділяєте лише пам'ять - ви насправді нічого не вкладаєте в неї. "Нормальна" програма виділила б фрагмент, а потім почала його використовувати. Виділення не те саме, що використання пам'яті.


3
Ласкаво просимо до публікації в Unix StackExchange. Це вкладає в нього дані, що дані просто дорівнюють нулю. Дивіться мемсету (). Ядро Linux забезпечує фізичну сторінку оперативної пам’яті, як тільки ви пишете на віртуальну сторінку; вона не дивиться на конкретне значення, яке записано.
sourcejedi

Насправді я скомпілював та запустив це на своєму робочому столі, починаючи з 2 ГБ, що використовуються, 6 Гб безкоштовно. Насправді він спочатку змінювався повільною швидкістю, і лише коли він досяг межі, він мінявся агресивно - що потім спричинило різні дії GUI.
Джеремі Боден
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.