Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Linux Memory Management

Linux Memory Management

Linux Memory Management

- NUMA;
- brk(), mmap(), malloc();
- Demand Paging;
- readahead.

http://habrahabr.ru/company/yandex/blog/250753/

Viacheslav Biriukov

February 17, 2015
Tweet

More Decks by Viacheslav Biriukov

Other Decks in Programming

Transcript

  1. Ответим на вопросы • Как максимально точно понять сколько памяти

    использует процесс? • Куда девается вся свободная память? • Если я раздаю файлы с диска зачем мне много памяти? • Почему запись быстрее чтения? • Почему перезапустить MySQL тяжелее чем MongoDB? • Почему я могу потерять данные при записи на диск? 4
  2. Немного терминов ︎Резидентная память (resident memory) – объём памяти, которая

    находится непосредственно в оперативной памяти системы (RAM). Анонимная память (anonymous memory) – память которая не связана ни с каким файлом на диске (without backing store). Page fault – ловушка (trap) обращения к памяти. Штатный механизм при работе с виртуальной памятью. 6
  3. Работа с памятью через страницы Страница – это минимальная единица

    памяти, с которой происходит работа. Размер страницы 4KB. Существуют Huge Pages – 2MB (не будем рассматривать). 7 page page page page page 0x0 0xFFFFFFFF … 4KB Адресное пространство page
  4. Процесс работает с виртуальной памятью 8 Адресное пространство процесса Основная

    память RAM Swap устройство • абстрактная модель; • упрощает разработку; • оставляем работу с настоящей памятью ОС; • позволяет превышать размеры основной памяти. Отображение памяти Paging/swapping Виртуальная память
  5. Настраиваем О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
  6. NUMA и SMP(UMA) 10 CPU 1 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 interconnect mem bus mem bus SMP NUMA CPU 2 CPU 1 CPU 2 RAM 1 RAM 2 RAM 1 RAM 2
  7. 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
  8. 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
  9. Read и Page Cache 14 Disk Storage read() syscall Page

    Cache no, miss 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
  10. 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
  11. Память процесса Сегменты: • stack; • mmap; • heap; •

    bss; • init data; • text.
 16 Stack (grows downwards) Text (program code) Initialized data Uninitialized data (bss) Heap (grows upwards) unallocated memory program break (brk) top of stack mmap region RLIMIT_STACK
  12. Как посмотреть • 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
  13. Virtual Memory Area (VMA) Область памяти (virtual memory area VMA)

    – описывает пространство адресов в памяти процесса (например 08048000-0804c000). Права на области: • Чтение (r); • Запись (w); • Исполнение (e).
 Области видимости и доступа: • приватные (p); • общие (s). 18
  14. Смотрим 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
  15. Выделение памяти 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)
  16. malloc() и free() glibc malloc() – выделяет анонимную память: •

    heap – для аллокации маленьких объёмов (≤128KB); • mmap() для остального. free() – освобождает память.
  17. Пример malloc() и brk() 22 Heap (grows upwards) program break

    (brk) unallocated memory Heap (grows upwards) new program break (brk) unallocated memory 1. Перед выделением памяти 2. После выделения памяти 110 KB 100 KB Если в heap не хватает памяти – вызывается brk(), который расширяет границы heap.
  18. mmap() и munmap() 23 mmap area /var/lib/db/index Виртуальная память процесса

    Диск mmap(fd, …) mmap() – позволяет отображать содержимое файла на 
 адресное пространство процесса.
 
 munmap() – освобождает память.
  19. Флаги mmap() Задаём видимость наших изменений: • MAP_PRIVATE и указание

    файла; • MAP_SHARED и указание файла. Можем явно задать уровень доступа: • PROT_READ; • PROT_WRITE. 24
  20. Page fault (demand paging) Allocated and mapped memory Only allocated

    Unallocated Address space of a process Page write syscall Page Table MMU TLB translate to physical RAM page fault Page page mapping Minor Page Fault – без обращения на диск.
  21. Типы Page Fault • Minor – без обращения на диск;

    • major – с обращением на диск; • invalid – ошибочное обращение (segmentation fault). 27
  22. 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
  23. Copy On Write (COW) 29 #0 #2 #1 free #3

    #0 #1 #2 #3 #4 Real Memory free #4 #0 #1 #2 #3 #4 Parent Child 1. После fork(). #0 #2 #1 change #3 change #1 #2 #3 #4 Real Memory free #4 #0 #1 #2 #3 #4 Parent Child 2. При попытке изменить страницу.
  24. malloc() и работа с файлами 31 free read(fd, buf, 8192)

    Kernel free free free /bin/ls find Page Cache Heap pages 1. Читаем файл /var/m.log. 2. Ядро проверяет страницы в кеше. miss m.log#0 free /bin/ls Page Cache libc.so 3. Кеширует страницы файла. free m.log#1 filled filled Heap 4. Копирует в user space буфер Kernel Kernel Disk Storage libc.so
  25. malloc() и работа с файлами • Используем больше памяти. •

    Копирование в user space – больше CPU и переключений контекста. 32
  26. mmap и работа с файлами 33 #0 #1 m.log#0 free

    /bin/ls Page Cache libc.so m.log#1 mmap area mmap() Простое отображение в Page Cache. #2
  27. mmap и minor page fault 34 #0 #1 m.log#0 free

    /bin/ls Page Cache libc.so m.log#1 mmap area mmap() #2 m.log#2 Обращение с странице в первый раз, которая уже в Page Cache. minor page fault
  28. mmap и major page fault (1) 35 #0 #1 m.log#0

    free /bin/ls Page Cache libc.so m.log#1 mmap area mmap() #2 free Обращение к странице в первый раз, которой нет в Page Cache major page fault m.log#0 free /bin/ls Page Cache libc.so m.log#1 m.log#2 Disk Storage 1. В Page Cache нет требуемой 
 страницы – major page fault. 2. Идём на диск и зачитываем 
 страницу в память.
  29. mmap и major page fault (2) 36 #0 #1 m.log#0

    free /bin/ls Page Cache libc.so m.log#1 mmap area mmap() #2 m.log#2 3. Связываем страницу с Page Cache.
  30. mmap() выводы 37 • Позволяет работать с файлами как с

    памятью. • “Lazy loading”. • Быстрее – меньше системных вызовов и переключений контекста. • Экономит память. • При завершении программы данные остаются в памяти.
  31. Мониторим память 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
  32. Работаем с 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
  33. Пару слов про readahead Управлять readahead можно: • readahead(); •

    madvise(); • posix_fadvise(); • blockdev --report
 
 blockdev --setra <value> <device>. 40
  34. Источники пополнения free list 42 Free page list Memory request

    Page Cache Swap (kswapd) Kernel memory (slab allocator) OOM Killer vm.swappiness 0 100 swap aggressively swap only to 
 avoid an OOM
  35. Page Scanning (kswapd) 43 min pages high pages low pages

    background synchronous time size of
 available
 free memory Регулируется vm.min_free_kbytes
  36. LRU/2 44 Active List Inactive List head tail head tail

    free page Free List referenced referenced tail head page allocation free pages reclaim
  37. 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
  38. 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
  39. Memory cgroup Можем ограничивать повсякому: • память; • память +

    swap; • свой OOM; • swappiness. Удобная статистика: # cat memory.stat
 …
 inactive_anon 0
 active_anon 0
 inactive_file 0
 active_file 0
 unevictable 0 47
  40. Почитать 49 Systems Performance: 
 Enterprise and the Cloud Linux

    Kernel Development Linux System Programming: 
 Talking Directly to the Kernel 
 and C Library