Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Вячеслав Бирюков - Как Linux работает с памятью

992 views

Published on

  • Be the first to comment

Вячеслав Бирюков - Как Linux работает с памятью

  1. 1. Как Linux работает с памятью Вячеслав Бирюков
  2. 2. Почему память? 3
  3. 3. Ответим на вопросы • Как максимально точно понять сколько памяти использует процесс? • Куда девается вся свободная память? • Если я раздаю файлы с диска зачем мне много памяти? • Почему запись быстрее чтения? • Почему перезапустить MySQL тяжелее чем MongoDB? • Почему я могу потерять данные при записи на диск? 4
  4. 4. Говорим про x86_64 Linux Kernel ≥ 2.6.32 5
  5. 5. Немного терминов ︎Резидентная память (resident memory) – объём памяти, которая находится непосредственно в оперативной памяти системы (RAM). Анонимная память (anonymous memory) – память которая не связана ни с каким файлом на диске (without backing store). Page fault – ловушка (trap) обращения к памяти. Штатный механизм при работе с виртуальной памятью. 6
  6. 6. Работа с памятью через страницы Страница – это минимальная единица памяти, с которой происходит работа. Размер страницы 4KB. Существуют Huge Pages – 2MB (не будем рассматривать). 7 Адресное пространство page page page page page 0x0 0xFFFFFFFF … 4KB page
  7. 7. Процесс работает с виртуальной памятью 8 Адресное пространство процесса Основная память RAM Swap устройство Отображение памяти Виртуальная память Paging/swapping • абстрактная модель; • упрощает разработку; • оставляем работу с настоящей памятью ОС; • позволяет превышать размеры основной памяти.
  8. 8. Настраиваем Оvercommit Глобальные настройки: • sysctl vm.overcommit_memory – 0 (default), 1, 2 • sysctl vm.overcommit_ratio / vm.overcommit_kbytes Следим за использованием overcommit: # cat /proc/meminfo … CommitLimit: 32973320 kB Committed_AS: 5510988 kB … 9
  9. 9. NUMA и SMP(UMA) 10 SMP CPU 1 CPU 2 System Bus Получаем список нод: # numactl --hardware available: 2 nodes (0-1) node 0 cpus: 0 1 2 3 4 5 6 7 16 17 18 19 20 21 22 23 node 0 size: 32735 MB node 0 free: 434 MB node 1 cpus: 8 9 10 11 12 13 14 15 24 25 26 27 28 29 30 31 node 1 size: 32768 MB node 1 free: 101 MB node distances: node 0 1 0: 10 21 1: 21 10 RAM 1 RAM 2 NUMA RAM 1 RAM 2 mem bus mem bus CPU 1 CPU 2 interconnect
  10. 10. Неравномерное заполнение NUMA Memory Nodes 30GB Управляем выделением памяти: # numactl --interleave all command 11 Node 1 Node 2 56GB
  11. 11. Memory Zones Из-за ограничений железа, ядро не может работать со всеми страницами одинаково. • ZONE_DMA • ZONE_DMA32 • ZONE_NORMAL Посмотреть какие зоны присутствуют: # grep zone /proc/zoneinfo Node 0, zone DMA Node 0, zone DMA32 Node 0, zone Normal Node 1, zone Normal 12
  12. 12. Page Cache Динамический размер → съест всю вашу память. По умолчанию все операции чтения и записи проходят через Page Cache. Посмотреть: # free -m total used free shared buffers cached Mem: 64401 64101 299 0 161 60339 -/+ buffers/cache: 3600 60800 Swap: 0 0 0 # grep Cached /proc/meminfo Cached: 61638200 kB 13
  13. 13. Read и Page Cache 14 read() syscall Page Cache no, miss Disk Storage yes Чтение происходит через Page Cache. Работает со страницами памяти и файла. mincore – системный вызов позволяет посмотреть находятся ли страницы файла в Page Cache. vmtouch – позволяет посмотреть сколько страниц в Page Cache’е: # vmtouch /var/lib/db/index Files: 1 Directories: 0 Resident Pages: 21365/21365 83M/83M 100% Elapsed: 0.004477 seconds hit
  14. 14. Write и Page Cache По умолчанию запись происходит только в Page Cache (исключение open() c O_SYNC). Страницы в кеше помечаются как грязные (dirty). Они сбрасываются на диск (writeback): •︎через заданный интервал времени vm.dirty_expire_centisecs (fsflush/pdflush); • система испытывает нехватку памяти (kswapd); • fsync() или msync(); • слишком много грязных страниц (vm.dirty_ratio и прочие). # grep Dirty /proc/meminfo … Dirty: 9604 kB … 15
  15. 15. Память процесса Сегменты: • stack; • mmap; • heap; • bss; • init data; • text. 16 Stack (grows downwards) unallocated memory Heap (grows upwards) Uninitialized data (bss) Initialized data Text (program code) top of stack program break (brk) mmap region RLIMIT_STACK
  16. 16. Как посмотреть •ps •top •cat /proc/<pid>/status … VmPeak: 8908 kB VmSize: 8908 kB VmLck: 0 kB VmPin: 0 kB VmHWM: 356 kB VmRSS: 356 kB VmData: 180 kB VmStk: 136 kB VmExe: 44 kB VmLib: 1884 kB VmPTE: 36 kB VmSwap: 0 kB … 17
  17. 17. Virtual Memory Area (VMA) Область памяти (virtual memory area VMA) – описывает пространство адресов в памяти процесса (например 08048000-0804c000). Права на области: • Чтение (r); • Запись (w); • Исполнение (e). Области видимости и доступа: • приватные (p); • общие (s). 18
  18. 18. Смотрим VMA Посмотреть: # pmap -x <pid> Address RSS Dirty Mode Mapping … 00007f0356b23000 76 76 rwx-- [ anon ] 00007f0356b38000 392 392 rwx-- [ anon ] 00007f0356bb9000 34708 0 r-xs- some_mapped_file 00007f0359272000 21876 0 r-xs- some_mapped_file2 … VMA кратко: # cat /proc/<pid>/maps … и очень подробно: # cat /proc/<pid>/smaps 19
  19. 19. Выделение памяти 20 Private Shared Anonymous • stack • malloc() • mmap(ANON, PRIVATE) • brk()/sbrk() • mmap(ANON, SHARED) File-backed • mmap(fd, PRIVATE) • binary/shared libraries • mmap(fd, SHARED)
  20. 20. malloc() и free() glibc malloc() – выделяет анонимную память: • heap – для аллокации маленьких объёмов (≤128KB); • mmap() для остального. free() – освобождает память.
  21. 21. Пример malloc() и brk() Если в heap не хватает памяти – вызывается brk(), который расширяет границы heap. 22 1. Перед выделением памяти 2. После выделения памяти Heap (grows upwards) program break (brk) unallocated memory Heap (grows upwards) new program break unallocated memory (brk) 110 KB 100 KB
  22. 22. mmap() и munmap() 23 mmap area mmap(fd, …) /var/lib/db/index Виртуальная память процесса Диск mmap() – позволяет отображать содержимое файла на адресное пространство процесса. munmap() – освобождает память.
  23. 23. Флаги mmap() Задаём видимость наших изменений: • MAP_PRIVATE и указание файла; • MAP_SHARED и указание файла. Можем явно задать уровень доступа: • PROT_READ; • PROT_WRITE. 24
  24. 24. На самом деле Linux не выделяет всю запрошенную память сразу. 25
  25. 25. Page fault (demand paging) Address space of a process Unallocated Only allocated Page Allocated and mapped memory write syscall TLB MMU Page Table page fault RAM translate to physical Page page mapping Minor Page Fault – без обращения на диск.
  26. 26. Типы Page Fault • Minor – без обращения на диск; • major – с обращением на диск; • invalid – ошибочное обращение (segmentation fault). 27
  27. 27. Page fault Страница может быть в следующем состоянии: 1. Unallocated; 2. Allocated, but unmapped (not yet faulted); 3. Allocated, and mapped to main memory (RAM); 4. Allocated, and mapped to the physical swap device (disk); Исходя из этого: ︎ RSS – размер 3-его пункта; ︎ Virtual Memory Size – сумма: 2 + 3 + 4. 28
  28. 28. Copy On Write (COW) 2. При попытке изменить страницу. 29 Parent Child #0 #2 #1 free #3 #0 #1 #2 #3 #4 Real Memory free #4 #0 #1 #2 #3 #4 1. После fork(). Parent Child #0 #2 #1 change #3 change #1 #2 #3 #4 Real Memory free #4 #0 #1 #2 #3 #4
  29. 29. Работа с файлами и памятью 30
  30. 30. malloc() и работа с файлами 31 1. Читаем файл /var/m.log. 2. Ядро проверяет страницы в кеше. read(fd, buf, 8192) free Kernel free free free /bin/ls find Page Cache Heap pages miss 3. Кеширует страницы файла. Page Cache m.log#0 free /bin/ls libc.so free m.log#1 Kernel 4. Копирует в user space буфер Heap filled filled Kernel Disk Storage libc.so
  31. 31. malloc() и работа с файлами • Используем больше памяти. • Копирование в user space – больше CPU и переключений контекста. 32
  32. 32. mmap и работа с файлами 33 Простое отображение в Page Cache. mmap() #0 #1 Page Cache m.log#0 free /bin/ls libc.so m.log#1 mmap area #2
  33. 33. mmap и minor page fault 34 Обращение с странице в первый раз, которая уже в Page Cache. mmap() #0 #1 Page Cache m.log#0 free /bin/ls libc.so m.log#1 mmap area #2 m.log#2 minor page fault
  34. 34. mmap и major page fault (1) 35 Обращение к странице в первый раз, которой нет в Page Cache mmap() #0 #1 Page Cache m.log#0 free /bin/ls libc.so m.log#1 mmap area #2 free major page fault Page Cache m.log#0 free /bin/ls libc.so m.log#1 m.log#2 Disk Storage 1. В Page Cache нет требуемой страницы – major page fault. 2. Идём на диск и зачитываем страницу в память.
  35. 35. mmap и major page fault (2) 36 3. Связываем страницу с Page Cache. mmap() #0 #1 Page Cache m.log#0 free /bin/ls libc.so m.log#1 mmap area #2 m.log#2
  36. 36. mmap() выводы 37 • Позволяет работать с файлами как с памятью. • “Lazy loading”. • Быстрее – меньше системных вызовов и переключений контекста. • Экономит память. • При завершении программы данные остаются в памяти.
  37. 37. Мониторим память sar ︎ -B: paging statistics: 02:46:04 pgpgin/s pgpgout/s fault/s majflt/s pgfree/s pgscank/s pgscand/s pgsteal/s %vmeff 02:46:05 0,00 134,00 1743,00 0,00 5978,00 0,00 0,00 0,00 0,00 02:46:06 0,00 108,00 9094,00 0,00 11801,00 0,00 0,00 0,00 0,00 -r: memory utilization: 02:41:50 kbmemfree kbmemused %memused kbbuffers kbcached kbcommit %commit kbactive kbinact 02:41:51 346644 65599996 99,47 191340 61669768 5410704 8,20 34115072 29384464 02:41:52 345900 65600740 99,48 191340 61669956 5410596 8,20 34114568 29384568 ︎ -R: memory statistics: 02:44:50 frmpg/s bufpg/s campg/s 02:44:51 393,00 4,00 45,00 02:44:52 -200,00 1,00 35,00 38
  38. 38. Работаем с Page Cache 1. Работать в обход Page Cache: • open(fd, O_DIRECT) – ходим мимо кеша (так делает MySQL с InnoDB). 2. Подсказать ядру, что в ближайшее время мы не будем работать с этим файлом и заставить его выгрузить страницы: • posix_fadvide(fd, POSIX_FADV_DONTNEED); • madvise(addr, MADV_DONTNEED); • mincore(). 3. Прибегнуть к помощи vmtouch (делает posix_fadvide): vmtouch -e /var/lib/db/index 39
  39. 39. Пару слов про readahead Управлять readahead можно: • readahead(); • madvise(); • posix_fadvise(); • blockdev --report blockdev --setra <value> <device>. 40
  40. 40. Освобождение памяти (page reclaiming) Страницы памяти: • unreclaimable; • swappable; • syncable; • discardable. 41
  41. 41. Источники пополнения free list 42 Memory request Free page list Page Cache Swap (kswapd) Kernel memory (slab allocator) OOM Killer 0 vm.swappiness 100 swap only to swap aggressively avoid an OOM
  42. 42. Page Scanning (kswapd) 43 high pages low pages min pages background synchronous time size of available free memory Регулируется vm.min_free_kbytes
  43. 43. LRU/2 44 referenced tail head Active List head Inactive List tail free page Free List referenced head tail page allocation free pages reclaim
  44. 44. LRU листы 45 Для каждой memory Node для каждой Zone и для каждой cgroup (kernel ≥ 3.3): • Active anon; • Inactive anon; • Active file; • Inactive file; • Unevictable. File backend LRU листы выравниваются по размерам. # cat /proc/meminfo … Active: 32714084 kB Inactive: 30755444 kB Active(anon): 1612548 kB Inactive(anon): 264 kB Active(file): 31101536 kB Inactive(file): 30755180 kB
  45. 45. Out Of Memory Killer (OOM) Логи: grep -i kill /var/log/messages* Меняем веса (-16 … 15, -17 – выключить): echo “-17” > /proc/<pid>/oom_adj Текущая сумма очков для pid: cat /proc/<pid>/oom_score 0 46
  46. 46. Memory cgroup Можем ограничивать повсякому: • память; • память + swap; • свой OOM; • swappiness. Удобная статистика: # cat memory.stat … inactive_anon 0 active_anon 0 inactive_file 0 active_file 0 unevictable 0 47
  47. 47. Cgroup page reclaiming • Global reclaiming. • Target reclaiming. 48
  48. 48. Почитать 49 Systems Performance: Enterprise and the Cloud Linux System Programming: Linux Kernel Development Talking Directly to the Kernel and C Library
  49. 49. Спасибо за внимание!

×