Коли моя система 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: Я подав помилку з помилкою ядра. Здається, привертає деяку увагу, так що ... пальці схрестили ...
vmstat 1>somefile
з системи, а потім побачити, про що вона повідомляє, після того, як система відновиться. Я спробую це.
swappiness
є 60 за замовчуванням (не те, що його зміна дає кращий результат). Ядро, яке використовується під час vmstat
виконання, - 4.14.35, але я спробував 4.15, 4.16 і навіть повернувся до серії 4.0 (!): Завжди однакова поведінка. І це не те, що я використовую якийсь дивний розподіл, це просто debian. Я не використовую зображення ядра від debian (не те, що у мене є незвичайні конфігурації), але я спробував одне з таких ... те саме поведінку.