[Linux] Причины фрагментации памяти и как избежать фрагментации памяти

Фрагментация памяти относится к неиспользуемому пространству между выделенными блоками памяти, что уменьшит использование памяти и повлияет на производительность и стабильность системы.

Основные причины фрагментации памяти
следующие:

  • Частое выделение и освобождение памяти: из-за несбалансированного выделения и освобождения памяти легко создать небольшие фрагменты.
  • Выделение памяти разного размера. Фрагментация также может возникнуть, если размер памяти, выделенной в системе, несовместим.
  • Проблема выравнивания памяти: когда память выделяется без выравнивания, это также вызывает фрагментацию.

Как избежать фрагментации памяти
Можно использовать следующие стратегии:

  • Пул памяти. Использование пула памяти может уменьшить частое выделение и высвобождение памяти, тем самым избегая фрагментации.
  • Унифицированный метод выделения памяти. Использование одного и того же метода выделения памяти позволяет избежать выделения памяти разных размеров.
  • Выровненное выделение памяти. Благодаря выравниванию распределения памяти фрагментация памяти может быть уменьшена.
  • Используйте алгоритм сжатия памяти: Алгоритм сжатия памяти может дефрагментировать память, чтобы уменьшить фрагментацию.
  • Избегайте утечек памяти: утечки памяти приведут к тому, что часть памяти не будет освобождена, а также приведет к фрагментации.

Подводя итог, можно сказать, что для предотвращения фрагментации памяти необходимо обратить внимание на способ выделения памяти, выравнивание памяти и предотвращение утечек памяти.

На практике есть два способа уменьшить фрагментацию памяти.
1. Освободить память и уменьшить фрагментацию
2. Сжать фрагментацию

В давно работающей операционной системе Linux в системном журнале иногда отображается сообщение об ошибке, которая не может выделить высокоуровневую память:

Aug  4 22:58:15 server1 kernel: : [69229257.683658] xenwatch: page allocation failure. order:4, mode:0xd0
Aug  4 22:58:15 server1 kernel: : [69229257.683665] Pid: 168, comm: xenwatch Tainted: GF          ---------------    2.6.32-358.23.2.el5.x86_64 #1
Aug  4 22:58:15 server1 kernel: : [69229257.683672] Call Trace:
Aug  4 22:58:15 server1 kernel: : [69229257.683688]  [<ffffffff8112723a>] ? __alloc_pages_nodemask+0x67a/0x8c0
Aug  4 22:58:15 server1 kernel: : [69229257.683697]  [<ffffffff8126082f>] ? number+0x2ff/0x330
Aug  4 22:58:15 server1 kernel: : [69229257.683706]  [<ffffffff81162260>] ? kmem_getpages+0x60/0x150
此时使用cat /proc/buddyinfo观察内存order分配情况,可以看到内存碎片化严重(大量的低阶内存页,但是几乎没有高阶内存页)
# cat /proc/buddyinfo
Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
Node 0, zone    DMA32  32995   4377    762    211    157    108     68     23      3      0      0
Node 0, zone   Normal 127146  68215   1614      0      0      0      0      0      0      0      1

Метод обработки в основном использует drop_caches (отказ от кеша), а затем использует compact_memory для объединения страниц памяти младшего порядка для создания достаточного количества страниц памяти высокого порядка.

drop_caches

Ядро после Linux Kernel 2.6.16 предоставляет ядро ​​​​настройки для сброса кеша страниц и / или каталогов (dentry) и кеша индексных узлов (inode), что может освободить много памяти.

### 释放页缓存
echo 1 > /proc/sys/vm/drop_caches

### 释放目录和索引节点缓存(inode and dentry cache)
echo 2 > /proc/sys/vm/drop_caches

### 同时释放 页、目录、索引节点缓存:
echo 3 > /proc/sys/vm/drop_caches

Вышеуказанные операции являются безвредными операциями и интеллектуально освобождают объекты памяти, которые вообще не используются. Грязные объекты будут продолжать использоваться до тех пор, пока они не будут записаны на диск, поэтому грязные объекты памяти не будут освобождены. Однако, если команда синхронизации выполняется до выполнения drop_caches, грязные объекты будут сброшены на диск, так что операция drop_caches высвободит больше памяти.

Примечание: drop_caches занимает некоторое время (это видно в терминале около десятков секунд), в это время, если снова использовать cat /proc/buddyinfo, можно увидеть, что сразу появляется большое количество старших страниц памяти .

Но триггерное действие drop_caches является одноразовым, то есть это не означает, что система не кэширует содержимое только потому, что выходное содержимое равно 3 при отображении cat /proc/sys/vm/drop_caches. Вместо этого, как только drop_caches завершается, система немедленно и автоматически кэширует последующие объекты памяти. Поэтому, чтобы снова запустить очистку кеша, ее нужно выполнить еще раз echo 3 > /proc/sys/vm/drop_caches.

Если повторение echo 3 > /proc/sys/vm/drop_cachesне освобождает кеш снова, вы можете сначала попробовать echo 0 > /proc/sys/vm/drop_caches, а затем сделать это снова echo 3 > /proc/sys/vm/drop_caches.

compact_memory

Когда для параметра компиляции ядра установлено значение CONFIG_COMPACTION, в /proc/sys/vm/compact_memory будет файл записи. Запись 1 в этот файл приводит к сжатию всех зон, чтобы предоставить как можно больше смежных блоков памяти. Эта функция очень важна, когда необходимо выделить большие страницы, но при необходимости процесс будет непосредственно выполнять сжатие памяти (компактную память).

Пример практической работы
Проверка перед очисткой кеша

#cat /proc/buddyinfo
Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
Node 0, zone    DMA32  32995   4377    762    211    157    108     68     23      3      0      0
Node 0, zone   Normal 127146  68215   1614      0      0      0      0      0      0      0      1

выполнить освобождение кеша

# echo 3 > /proc/sys/vm/drop_caches

Проверить после очистки кеша

# cat /proc/buddyinfo
Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
Node 0, zone    DMA32  76826  65298  43784  20780   5272    616     90     32      4      0      0
Node 0, zone   Normal 524538 365499 176074  45644   4338    140      6      0      0      0      1

начать сжатие

Выполнить сжатие памяти

# echo 1 > /proc/sys/vm/compact_memory

Затем снова проверьте распределение страниц памяти, вы можете увидеть, что постепенно появляется все больше и больше старших страниц памяти.

# cat /proc/buddyinfo
Node 0, zone      DMA      2      2      2      1      2      1      1      0      0      0      2
Node 0, zone    DMA32  18217  13464   8621   4666   2654   2087   1609   1040    517    130      3
Node 0, zone   Normal 145048 131183  76864  38454  20405  11854   5149   1143     96      3      1

Справочная статья: https://blog.csdn.net/qq_31055683/article/details/126974873

Guess you like

Origin blog.csdn.net/imliuqun123/article/details/129850594