Очень высокое использование кэша, вызывающее замедление

Я пытаюсь определить виновника того, что делает мой персональный компьютер крайне вялым. Самый большой подозреваемый это память. Когда компьютер работает быстро, моя кеш-память выглядит нормально. Однако, когда он работает медленно, это выглядит так:

luke@Luke-XPS-13:~$ free -m
              total        used        free      shared  buff/cache   available
Mem:           7830        1111        1090         277        5628        1257
Swap:         16077         665       15412

и это:

luke@Luke-XPS-13:~$ vmstat -S M
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 3  0    665   1065     67   5562    0    0    34    88   43   23 13  4 82  0  0

Кэши занимают 5,5 ГБ моей 8 ГБ памяти, когда все программы закрыты и после запуска

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

которая должна быть силой, очищающей их. Как только компьютер начинает погружаться в своп, его игра заканчивается на приемлемой скорости. Выключение временно устраняет проблему, но в конечном итоге она возвращается, и я не могу понять, что ее вызывает. Slabtop рассказывает немного больше о виновнике, но я не уверен, что это означает. Зачем kmalloc-4096?

 Active / Total Objects (% used)    : 1554043 / 1607539 (96.7%)
 Active / Total Slabs (% used)      : 167569 / 167569 (100.0%)
 Active / Total Caches (% used)     : 76 / 109 (69.7%)
 Active / Total Size (% used)       : 5091450.96K / 5105920.97K (99.7%)
 Minimum / Average / Maximum Object : 0.01K / 3.18K / 18.50K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
1254755 1254755 100%  4.00K 156847        8   5019104K kmalloc-4096
  5430   5430 100%    2.05K    362       15     11584K idr_layer_cache
 20216   9010  44%    0.57K    722       28     11552K radix_tree_node
  8820   7358  83%    1.05K    294       30      9408K ext4_inode_cache
 38577  25253  65%    0.19K   1837       21      7348K dentry
 12404  11432  92%    0.55K    443       28      7088K inode_cache
 30120  29283  97%    0.20K   1506       20      6024K vm_area_struct
 31722  31722 100%    0.12K    933       34      3732K kernfs_node_cache
 13696  12514  91%    0.25K    856       16      3424K kmalloc-256
 27144  27134  99%    0.10K    696       39      2784K buffer_head
 41088  29789  72%    0.06K    642       64      2568K kmalloc-64
   632    567  89%    3.75K     79        8      2528K task_struct
  2432   2274  93%    1.00K    152       16      2432K kmalloc-1024
  3048   2677  87%    0.64K    127       24      2032K shmem_inode_cache
   912    845  92%    2.00K     57       16      1824K kmalloc-2048
   172    162  94%    8.00K     43        4      1376K kmalloc-8192
  1736   1561  89%    0.56K     62       28       992K ecryptfs_key_record_cache
  5103   4073  79%    0.19K    243       21       972K kmalloc-192
  1792   1626  90%    0.50K    112       16       896K kmalloc-512
  1456   1456 100%    0.61K     56       26       896K proc_inode_cache
 10149   8879  87%    0.08K    199       51       796K anon_vma
 24960  19410  77%    0.03K    195      128       780K kmalloc-32
   360    352  97%    2.06K     24       15       768K sighand_cache

3 ответа

Исходя из ваших комментариев, вы говорите, что использование кэша заметно не падает, когда вы пытаетесь echo 3 > /proc/sys/vm/drop_caches

Это может произойти, только если это кеш для записи. Если вы записываете 5 ГБ в некоторые файлы, данные немедленно попадают в кэш, и ваша программа продолжается. Кеш на самом деле записывается в хранилище в фоновом режиме как можно быстрее. В вашем случае хранилище кажется очень медленным, и вы накапливаете неписанный кеш, пока он не истощит всю вашу оперативную память и не начнет выталкивать все из памяти для замены.

Ядро никогда не запишет кеш в раздел подкачки. Он хранит его в оперативной памяти, пока он не будет безопасно записан в место назначения.

Ядро никогда не удалит неписанный кеш, потому что это приведет к потере данных (вы сохранили файл, поэтому вы ожидаете, что данные попадут в постоянное хранилище).

Вы можете решить это только за счет ускорения хранения. Эта проблема часто наблюдается в хранилище, смонтированном по сети (проверьте mount для типов cifs, nfs, sshfsи т. д.) или медленные устройства USB1.

Вы также можете сделать проблему гораздо менее существенной для системы, закрыв грязный кеш sysctl vm.dirty_ratio=10 прежде чем он станет слишком много.

dirty_ratio

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

Общая доступная память не равна общей системной памяти.

Если это правильный диагноз, вы увидите, что кеш легко удаляется (по крайней мере, на 90%) и что процесс записи этих гигабайт становится очень медленным. Остальная часть системы станет более отзывчивой.

Свободная память выделяется для дискового кэша. Это нормально.

Медлительность, вызванная использованием свопа, также является нормальной. Тем не менее, ваш своп примерно вдвое больше необходимого размера.

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

Сразу после перезагрузки, попробовать на лету, в terminal тип:

sudo sysctl -w vm.swappiness=10

Если это поможет, сделайте его постоянным, отредактировав:

gksudo gedit /etc/sysctl.conf

и добавление:

# adjust swap vs ram ratio, default=60
vm.swappinesss=10

до конца файла сохраните и выйдите, перезагрузите компьютер.

Я бы порекомендовал пару вещей:

  1. Проверять cat /proc/meminfoи осматривать и Shmem. Если вы запускаете программное обеспечение, которое использует много разделяемой памяти, это будет учитываться Cachedно это не кеш в традиционном смысле, от которого можно отказаться, когда потребуется больше оперативной памяти. Подробности см. в обсуждении на странице https://lkml.org/lkml/2021/8/30/635 . Обычно это лучший показатель реально используемой памяти, которую можно получить, немедленно удалив все возможные кэши и используя всю свободную память вместе. Обратите внимание, что MemAvailableявляется статистикой, а не точным значением, поэтому оно может немного отставать при очень интенсивном использовании памяти.

  2. Попробуйте увеличить /proc/sys/vm/vfs_cache_pressure. По умолчанию это 100но если вам немного не хватает памяти, вы можете попробовать увеличить это (например, echo 150 > /proc/sys/vm/vfs_cache_pressureв качестве root). Теоретически это должно снизить производительность, чтобы увеличить доступную для приложений оперативную память за счет уменьшения дискового кэширования. Это уменьшит общую пропускную способность вашего диска, но может уменьшить задержку в худшем случае в случаях, когда оперативной памяти становится мало.

  3. Бежать cat /proc/buddyinfoи убедитесь, что у вас есть свободные блоки для всех размеров блоков. В основном любые строки со словом Normalне должно быть нуля ни в одном столбце. Если у вас есть нули, особенно ближе к концу строки, и большие числа в начале, ваша система страдает от фрагментации памяти. Если вы страдаете от фрагментации памяти, попробуйте запустить echo 1 > /proc/sys/vm/compact_memory. Если это помогает повысить производительность системы на короткое время, ваша система страдает от фрагментации памяти, и вам следует попытаться либо использовать больше мощности ЦП для более частого автоматического сжатия памяти, либо исправить программное обеспечение, вызывающее сильную фрагментацию. Некоторые люди заканчивают тем, что добавляют cronработа для эха 1 для compact_memoryкаждые N минут, но я считаю, что это грубый обходной путь, а не реальное исправление.

Другие вопросы по тегам