Це старий пост, однак я все-таки мав би сміливо викладати свої думки тут.
Починаючи знизу, Linux спочатку розділив би пам'ять на сторінки (зазвичай 4K на сторінку в системі x86_64). Після цього створюється віртуальна пам'ять, відображення якої здійснюється за допомогою фізичної пам'яті за допомогою MMU (Unit Management Memory Unit).
Процеси розподіляються пам'яттю з області віртуальної пам'яті, тому, зверніть увагу, коли ви бачите / proc / meminfo, ви побачите VMalloc * як деталі віртуальної пам'яті.
Скажімо, у вас є процес, який вимагає пам'яті (скажімо, 300 Мб - веб-браузер). На процес буде виділено 300 МБ з віртуальної пам'яті, однак, це не обов'язково, це пам'ять відображена (тобто відображена у фізичну пам'ять). Існує концепція "Копіювати на запис" для управління пам'яттю, згідно з якою, якщо ваші процеси фактично використовують пам'ять, виділену з віртуальної пам'яті (тобто це робить деякий запис у пам'яті), то лише тоді вона відображається у фізичну пам'ять. Це допомагає ядру ефективно працювати в багатопроцесорному середовищі.
Що таке кеш?
Багато пам'яті, що використовується процесами, є спільним. Скажімо, бібліотека glibc використовується майже у всіх процесах. Який сенс зберігати в пам’яті кілька копій glibc, коли кожен процес може отримати доступ до одного місця пам’яті та зробити свою роботу. Такі часто використовувані ресурси зберігаються в кеші, щоб, коли процеси вимагають, на них можна було б посилатися на одне місце пам’яті. Це допомагає прискорити процеси, оскільки читання glibc (тощо) знову і знову з диска забирає багато часу.
Сказане було сказано для бібліотек, що використовуються спільно, подібне також стосується читання файлів. Якщо ви прочитаєте великий файл (скажімо, 100-200MB) вперше, це займе багато часу. Однак, коли ви спробуєте зробити те ж саме, прочитайте ще раз, це було б швидше. Дані були кешовані в пам'яті, і повторне читання було зроблено не для всіх блоків.
Що таке буфер?
Що стосується буфера, то коли процес робить файл вводу / виводу, він покладається на буфер ядра для запису даних на диск. Обробляє, запитує ядро виконати роботу. Отже, від імені процесу ядро записує дані у свій "буфер" і повідомляє процесу, що запис робиться. Таким чином, ядро буде тримати синхронізацію цих даних у буфері на диску. Таким чином, процеси покладаються на ядро, щоб вибрати правильний час для синхронізації даних на диску, і процеси можуть продовжувати працювати вперед. Пам'ятайте, що це звичайні введення-виведення, які нормальні процеси роблять. Однак спеціалізовані процеси, які потребують підтвердження того, що введення-виведення насправді робиться на диску, можуть використовувати інший механізм для вводу-виводу на диску. Деякі утиліти з відкритим кодом - libaio. Також існують способи виклику явної синхронізації з FD, відкритими в контексті ваших процесів,
Які тоді несправності сторінки?
Розглянемо приклад, коли ви запускаєте процес (скажімо, веб-браузер), двійковий код якого становить близько 300 Мб. Однак повний 300 Мб двійкового веб-браузера не працює миттєво. Процес продовжує переходити від функцій до функцій у своєму коді. Як було сказано раніше, віртуальна пам'ять споживає 300 Мб, проте не все є пам'яттю, відображеною на фізичну пам'ять (RSS - пам'ять резидента буде менше, див. Верхній вихід). Коли виконання коду досягне точки, для якої пам'ять насправді не відображається фізично, виникне помилка сторінки. Ядро буде відображати цю пам'ять у фізичну, пов’язувати сторінку пам'яті з вашим процесом. Така помилка сторінки називається "Незначні помилки сторінки". Аналогічно, коли процес виконує файли, виникають помилки основних сторінок вводу / виводу.
Коли і чому відбувається Swap Out?
Ситуація 1:
Враховуючи деталі, наведені вище, давайте розглянемо сценарій, коли хороший об'єм пам'яті стане відображеним у пам'яті. А зараз запускаються процеси, для яких потрібна пам'ять. Як обговорювалося вище, ядро доведеться зробити деяке відображення пам'яті. Однак для картографування пам’яті недостатньо фізичної оперативної пам’яті. Тепер ядро спочатку загляне в кеш, воно матиме старі сторінки пам'яті, які не використовуються. Він перенесе ці сторінки на окремий розділ (званий SWAP), звільнить деякі сторінки та відобразить звільнені сторінки до нового запиту, що надходить. Оскільки запис на диску відбувається набагато повільніше, ніж твердотільна ОЗУ, цей процес займає багато часу, а значить, спостерігається уповільнення.
Ситуація 2:
Скажімо, ви бачите багато вільної пам'яті, доступної в системі. Вже тоді ви бачите, що відбувається багато замінів. Можлива проблема фрагментації пам'яті. Розглянемо процеси, які вимагають 50 МБ суміжної пам'яті з ядра. (майте на увазі суміжні). Очевидно, ядро виділяло б сторінки випадковим чином різним процесам і звільнило деякі з них. Однак, коли ми вимагаємо суміжної пам’яті, їй доведеться шукати шматок, який задовольняє попит процесів. Якщо вона не в змозі отримати таку пам’ять, доведеться зробити заміну деяких старих сторінок пам'яті, а потім виділити суміжні. Навіть у таких випадках SWAP вийде. Починаючи з ядра версії 2.6 і вище, такі проблеми з фрагментацією значно зменшилися. Однак якщо система працює тривалий час, такі проблеми все-таки можуть виникнути.
Дивіться цей приклад ( вихід vmstat )
2016-10-29 03:55:32 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
2016-10-29 03:55:32 r b swpd free buff cache si so bi bo in cs us sy id wa st
2016-10-30 03:56:04 19 23 2914752 4692144 3344908 12162628 1660 1 8803 12701 4336 37487 14 7 40 38 0
2016-10-30 03:56:34 3 20 2889296 4977580 3345316 12026752 2109 2 8445 14665 4656 36294 12 7 46 34 0
2016-10-30 03:57:04 1 11 3418868 4939716 3347804 11536356 586 4744 2547 9535 3086 24450 6 3 59 33 0 <<<-----
2016-10-30 03:57:34 3 19 3456252 5449884 3348400 11489728 3291 13371 6407 17957 2997 22556 6 4 66 24 0
2016-10-30 03:58:04 7 6 4194500 5663580 3349552 10857424 2407 12240 3824 14560 2295 18237 4 2 65 29 0
2016-10-30 03:58:34 2 16 4203036 5986864 3348908 10838492 4601 16639 7219 18808 2575 21563 6 4 60 31 0
2016-10-30 03:59:04 3 14 4205652 6059196 3348760 10821448 6624 1597 9431 4357 1750 20471 6 2 60 31 0
2016-10-30 03:59:34 2 24 4206968 6053160 3348876 10777216 5221 2067 10106 7377 1731 19161 3 3 62 32 0
2016-10-30 04:00:04 0 13 4205172 6005084 3348932 10785896 6236 1609 10330 6264 1739 20348 4 2 67 26 0
2016-10-30 04:00:34 4 11 4206420 5996396 3348976 10770220 6554 1253 10382 4896 1964 42981 10 5 58 27 0
2016-10-30 04:01:04 6 4 4177176 5878852 3348988 10825840 8682 765 10126 2716 1731 32949 8 4 69 19 0
@ 2016-10-30 03:57:04 ми бачимо, що є ще хороша кількість безкоштовної оперативної пам’яті. Однак навіть тоді відбувся своп. У цей момент ми перевірили дерево процесів, і не побачили жодного процесу, який вимагав би такого великого обсягу пам'яті (більше, ніж вільної пам'яті). Очевидною підозрою була ситуація 2, описана вище. Ми перевірили журнали buddyinfo та zoneinfo вище (Використовуйте echo m> / proc / sysrq-тригер, щоб перевірити їх, вихід надходить у syslogs).
Для звичайної нашої системи порівняння інформації про зону іде так. А графіки для кешу / вільного / низького пам’яті також згадуються нижче
Переглядаючи інформацію, зрозуміло, що у вузлі 0 та вузлі 1 нормально є фрагментація пам'яті (Вузол - це машина на базі NUMA, отже, декілька вузлів (див. Numactl для перевірки інформації для вашої системи).
Фрагментація пам’яті також є причиною того, що використання свопів може збільшуватися навіть тоді, коли вільна пам'ять є.