Фрагментація пам'яті Linux


20

Чи є спосіб виявити фрагментацію пам'яті на Linux? Це тому, що на деяких довго працюючих серверах я помітив погіршення продуктивності і лише після перезавантаження процесу я бачу кращі показники. Я помітив це більше, коли використовувався підтримка величезної сторінки Linux - чи величезні сторінки в Linux більш схильні до фрагментації?

Я переглянув / proc / buddyinfo зокрема. Хочеться знати, чи є якісніші способи (не лише команди CLI як такої, будь-яка програма чи теоретичні передумови).


Я не дивлюся лише на швидкі рішення командного рядка, будь-яка проста програма / теорія також буде робити. Отже, я не запитував у сервері за замовчуванням.
Рагу

1
Я не розумію тут жодного моменту. Наскільки я розумію, фрагментація пам'яті повинна призвести до браку пам’яті і, як результат, до помилок розподілу пам’яті. Однак ви запитуєте про зниження продуктивності. Це тому, що у вас багато пам’яті замінено на диск? А якщо так, що давати vmstatв полі so?

@skwllsp - Відредагував мою відповідь, щоб бути більш конкретним.
Tim Post

@Raghu - Я б не очікував, що більшість системних адміністраторів модифікують код ядра, щоб змусити управління пам’яттю вести себе по-різному, проте кваліфіковані адміністратори Linux повинні знати хоча б огляд того, як Linux управляє пам'яттю. Це питання дійсно наголос. Я проголосував за перенесення його просто тому, що не можу запропонувати (у своїй відповіді) код, який відповідає на ваше запитання. Читання з / proc чи користування vmstat- це звичайний досвід користувача. Якби ви писали програму, щоб зробити те саме, було б інакше. Якщо ви збираєтесь використовувати bash для збирання цієї інформації, відредагуйте своє запитання, воно не буде закрито :)
Tim Post

@Tim - Оскільки я запропонував, що це не просто команди bash / cli, яких я хотів знати, мені потрібна була інформація, щоб допомогти мені в процедурі бенчмаркінгу (аналізувати результати, а не запускати їх).
Рагу

Відповіді:


12

Я відповідаю на тег . Моя відповідь специфічна лише для Linux .

Так, величезні сторінки більш схильні до фрагментації. Є два види пам’яті, той, який отримує ваш процес (віртуальний) і той, яким керує ядро ​​(реальний). Чим більша будь-яка сторінка, тим складніше буде згрупувати (і зберегти з нею) своїх сусідів, особливо коли ваша служба працює в системі, яка також повинна підтримувати інших, які за замовчуванням виділяють і записують у спосіб більше пам'яті, ніж вони фактично в кінцевому рахунку використовувати.

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

Причина, по якій ви бачите погіршену продуктивність на довго працюючих серверах, швидше за все, тому, що виділені блоки, які не були явно заблоковані (наприклад, mlock()/ mlockall()або posix_madvise()) і не були змінені протягом певного часу, були завантажені на сторінку , а це означає, що ваші службові ковзання на диск, коли він повинен читати їх. Змінення такої поведінки робить ваш процес поганим сусідом , тому багато людей ставлять свої RDBMS на зовсім інший сервер, ніж web / php / python / ruby ​​/ будь-який інший. Єдиний спосіб виправити це, справедливо, - зменшити конкуренцію за сусідні блоки.

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

Насправді, повторний запуск (скажімо так, "apache" під великим навантаженням, швидше за все, відправить блоки, що належать іншим службам, прямо на диск. Так, так, "apache" покращиться на короткий час, але "mysql" може страждати .. принаймні, поки ядро ​​не змусить їх страждати однаково, коли просто не вистачає достатньої фізичної пам'яті.

Додайте більше пам’яті або розділіть вимогливих malloc()споживачів :) Це не просто фрагментація, на яку потрібно дивитися.

Спробуйте vmstatотримати огляд того, що насправді зберігається де.


Дякую за відповідь. Я використовував величезні сторінки (розмір = 2048 КБ кожна) для mysql - innodb буферний пул, - щоб побачити, наскільки добре він працює (використовуючи sysbench). Спочатку, коли тривалість процесу (і навіть часу роботи системи) була низькою, це дало дуже хороші результати. Однак її продуктивність почала погіршуватися протягом кількох пробіжок. Щодо згадуваної вами сторінки, я, безумовно, помітив високу активність віртуального комп'ютера, але я припускав, що це могло бути через тестування тесту та журналу innodb (активність vm вище з величезними сторінками, ніж без). Я також встановив vm.swappiness на 1. Я не міг помітити жодної різкої зміни.
Раггу

Згідно з чудовим посібником , "величезні сторінки не можуть бути замінені під тиском пам'яті". Я думаю, що це хороша відповідь у w / r / t стандартній пам'яті, але не для величезних сторінок.
Dan Pritts

5

Ядро

Щоб отримати поточний індекс фрагментації, використовуйте:

sudo cat /sys/kernel/debug/extfrag/extfrag_index

Для дефрагментації пам'яті ядра спробуйте виконати:

sysctl vm.compact_memory=1  

Також ви намагаєтесь вимкнути прозорі величезні сторінки (він же THP) та / або відключити swap (або зменшити swappiness).

Простір користувачів

Щоб зменшити фрагментацію простору користувача, ви можете спробувати інший розподільник, наприклад jemalloc(він має чудові можливості самоаналізу , що дасть вам внутрішню фрагментацію розподільника).

Ви можете перейти на користувацький malloc, перекомпілювавши програму разом із ним або просто запустивши програму за допомогою LD_PRELOAD: LD_PRELOAD=${JEMALLOC_PATH}/lib/libjemalloc.so.1 app (остерігайтеся взаємодії між THP та розподільниками пам'яті пам'яті )

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


1
Чому ви думаєте, що відключення swap може допомогти? Мені здається більш ймовірним, що відключення swap зашкодить ще більше.
kasperd

1
Оскільки в початковій публікації недостатньо інформації, можливо, процес просто протікає і починає міняти місцями. Крім того, я не бачу законних причин використання swap майже в будь-якій виробничій системі (mb тільки для спільних робочих станцій для студентів).
SaveTheRbtz

2
Достатня кількість місця для заміни підвищить продуктивність. Проблеми з продуктивністю, які ви отримаєте, якщо у вас недостатньо місця для заміни, є достатньою причиною, щоб ввімкнути можливість заміни.
kasperd

1
@SaveTheRbtz Хороша причина використовувати своп у виробничій системі - це те, що вона дає системі більше можливостей, які вона використовуватиме, лише якщо вважає, що вони вигідні. Крім того, він дозволяє видозміненим сторінкам, до яких не можна отримати доступ за години (і ніколи не можна отримати), викидати з дорогоцінної фізичної пам'яті. Нарешті, це дозволяє системі добросовісно обробляти випадки, коли зарезервовано набагато більше пам’яті, ніж використовується.
Девід Шварц

2
"тільки якщо він вважає, що вони вигідні", - це додає додаткової евристичності та зробить систему менш передбачуваною. Також алгоритми заміни сторінок (використовуються в swap та анонімні mmap) реалізуються по-різному на різних ядрах (наприклад, Linux проти FreeBSD) або навіть різних версіях однієї ОС (2.6.32 проти 3.2 проти 3.10) .. "це дозволяє змінювати сторінки [. ..], яку потрібно викинути з [...] фізичної пам'яті "- це приховає витоки пам'яті. "обробляти випадки, коли набагато більше пам'яті зарезервовано, ніж використовується" - повільна система набагато гірша, ніж система, тому "розумність" сумнівна.
SaveTheRbtz

4

Використання величезних сторінок не повинно викликати додаткової фрагментації пам'яті в Linux; Підтримка Linux для величезних сторінок призначена лише для спільної пам'яті (через shmget або mmap), і будь-які використовувані величезні сторінки повинні бути спеціально запитані та попередньо розміщені системним адміністратором. Потрапивши в пам'ять, вони там закріплюються, і їх не замінюють. Завдання заміни величезних сторінок перед фрагментацією пам’яті полягає саме в тому, що вони залишаються закріпленими в пам’яті (при виділенні величезної сторінки розміром 2 Мб ядро ​​повинно знайти 512 суміжних вільних 4 КБ сторінок, які можуть навіть не існувати).

Документація Linux на величезних сторінках: http://lwn.net/Articles/375098/

Є одна обставина, коли фрагментація пам’яті може спричинити повільне розміщення величезних сторінок (але не там, де величезні сторінки викликають фрагментацію пам’яті), і це якщо ваша система налаштована розробити пул величезних сторінок, якщо цього вимагає програма. Якщо / proc / sys / vm / nr_overcommit_hugepages більше / proc / sys / vm / nr_hugepages, це може статися.


Справді, - і це, як правило, повинно сприяти продуктивності, оскільки воно запобіжить пропуски TLB (пояснення див. У пов’язаній статті).
Dan Pritts

0

Є /proc/buddyinfoщо дуже корисно. Це корисніше з хорошим вихідним форматом, як це може зробити цей скрипт Python:

https://gist.github.com/labeneator/9574294

На величезних сторінках потрібно кілька безкоштовних фрагментів розміром 2097152 (2 Мбіт) або більше. Для прозорих величезних сторінок воно буде автоматично ущільнюватися, коли ядро ​​запитується для деяких, але якщо ви хочете побачити, скільки ви можете отримати, тоді як root run:

echo 1 | sudo tee /proc/sys/vm/compact_memory

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

У мене є рішення, яке працює для мене. Я використовую його на декількох серверах і на своєму ноутбуці. Він чудово працює для віртуальних машин.

Додайте kernelcore=4Gпараметр до командного рядка ядра Linux. На своєму сервері я використовую 8G. Будьте обережні з номером, тому що це не дозволить вашому ядру виділити що-небудь поза цією пам'яттю. Сервери, яким потрібно багато буферів сокет або ж цей потічний диск записують на сотні дисків, не люблять обмежуватися таким чином. Будь-який розподіл пам'яті, який потрібно "закріпити" на плиті або DMA, відноситься до цієї категорії.

Вся ваша інша пам’ять потім стає «рухомою», а значить, її можна ущільнити в приємні шматки для величезного розміщення сторінок. Тепер прозорі величезні сторінки дійсно можуть зніматись і працювати так, як належить. Кожен раз, коли ядро ​​потребує більше 2М сторінок, воно може просто переставити 4K сторінки десь ще.

І я не зовсім впевнений, як це взаємодіє з прямим введенням нульової копії. Пам'ять у "рухомій зоні" не повинна бути закріплена, але прямий запит вводу-виводу зробив би саме це для DMA. Це може скопіювати це. Це все одно може зафіксувати його в рухомій зоні. В будь-якому випадку це, мабуть, не саме те, що ви хотіли.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.