Как Linux работает 
с памятью 
Вячеслав Бирюков
Почему память? 
3
Ответим на вопросы 
• Как максимально точно понять сколько памяти использует 
процесс? 
• Куда девается вся свободная память? 
• Если я раздаю файлы с диска зачем мне много памяти? 
• Почему запись быстрее чтения? 
• Почему перезапустить MySQL тяжелее чем MongoDB? 
• Почему я могу потерять данные при записи на диск? 
4
Говорим про 
x86_64 
Linux Kernel ≥ 2.6.32 
5
Немного терминов 
︎Резидентная память (resident memory) – объём памяти, которая 
находится непосредственно в оперативной памяти системы (RAM). 
Анонимная память (anonymous memory) – память которая не 
связана ни с каким файлом на диске (without backing store). 
Page fault – ловушка (trap) обращения к памяти. Штатный механизм 
при работе с виртуальной памятью. 
6
Работа с памятью через страницы 
Страница – это минимальная единица 
памяти, с которой происходит работа. 
Размер страницы 4KB. 
Существуют Huge Pages – 2MB (не 
будем рассматривать). 
7 
Адресное пространство 
page 
page 
page 
page 
page 
0x0 
0xFFFFFFFF 
… 
4KB 
page
Процесс работает с виртуальной памятью 
8 
Адресное пространство процесса 
Основная память 
RAM 
Swap 
устройство 
Отображение памяти 
Виртуальная память 
Paging/swapping 
• абстрактная модель; 
• упрощает разработку; 
• оставляем работу с настоящей памятью ОС; 
• позволяет превышать размеры основной памяти.
Настраиваем О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
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
Неравномерное заполнение NUMA 
Memory Nodes 
30GB 
Управляем выделением памяти: 
# numactl --interleave all command 
11 
Node 1 Node 2 
56GB
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
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
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
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
Память процесса 
Сегменты: 
• 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
Как посмотреть 
•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
Virtual Memory Area (VMA) 
Область памяти (virtual memory area VMA) – описывает пространство 
адресов в памяти процесса (например 08048000-0804c000). 
Права на области: 
• Чтение (r); 
• Запись (w); 
• Исполнение (e). 
Области видимости и доступа: 
• приватные (p); 
• общие (s). 
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
Выделение памяти 
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)
malloc() и free() 
glibc malloc() – выделяет анонимную память: 
• heap – для аллокации маленьких объёмов (≤128KB); 
• mmap() для остального. 
free() – освобождает память.
Пример 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
mmap() и munmap() 
23 
mmap area 
mmap(fd, …) 
/var/lib/db/index 
Виртуальная память процесса 
Диск 
mmap() – позволяет отображать содержимое файла на 
адресное пространство процесса. 
munmap() – освобождает память.
Флаги mmap() 
Задаём видимость наших изменений: 
• MAP_PRIVATE и указание файла; 
• MAP_SHARED и указание файла. 
Можем явно задать уровень доступа: 
• PROT_READ; 
• PROT_WRITE. 
24
На самом деле Linux 
не выделяет всю запрошенную 
память сразу. 
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 – без обращения на диск.
Типы Page Fault 
• Minor – без обращения на диск; 
• major – с обращением на диск; 
• invalid – ошибочное обращение (segmentation fault). 
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
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
Работа с файлами и памятью 
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
malloc() и работа с файлами 
• Используем больше памяти. 
• Копирование в user space – больше CPU и переключений контекста. 
32
mmap и работа с файлами 
33 
Простое отображение в Page Cache. 
mmap() 
#0 
#1 
Page Cache 
m.log#0 
free 
/bin/ls 
libc.so 
m.log#1 
mmap area 
#2
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
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. Идём на диск и зачитываем 
страницу в память.
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
mmap() выводы 
37 
• Позволяет работать с файлами как с памятью. 
• “Lazy loading”. 
• Быстрее – меньше системных вызовов и переключений 
контекста. 
• Экономит память. 
• При завершении программы данные остаются в памяти.
Мониторим память 
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
Работаем с 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
Пару слов про readahead 
Управлять readahead можно: 
• readahead(); 
• madvise(); 
• posix_fadvise(); 
• blockdev --report 
blockdev --setra <value> <device>. 
40
Освобождение памяти (page reclaiming) 
Страницы памяти: 
• unreclaimable; 
• swappable; 
• syncable; 
• discardable. 
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
Page Scanning (kswapd) 
43 
high pages 
low pages 
min pages 
background 
synchronous 
time 
size of 
available 
free memory 
Регулируется vm.min_free_kbytes
LRU/2 
44 
referenced 
tail head 
Active List 
head Inactive List tail 
free page 
Free List 
referenced 
head tail 
page allocation 
free pages 
reclaim
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
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
Memory cgroup 
Можем ограничивать повсякому: 
• память; 
• память + swap; 
• свой OOM; 
• swappiness. 
Удобная статистика: 
# cat memory.stat 
… 
inactive_anon 0 
active_anon 0 
inactive_file 0 
active_file 0 
unevictable 0 
47
Cgroup page reclaiming 
• Global reclaiming. 
• Target reclaiming. 
48
Почитать 
49 
Systems Performance: 
Enterprise and the Cloud 
Linux System Programming: Linux Kernel Development 
Talking Directly to the Kernel 
and C Library
Спасибо за внимание!

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

  • 2.
    Как Linux работает с памятью Вячеслав Бирюков
  • 3.
  • 4.
    Ответим на вопросы • Как максимально точно понять сколько памяти использует процесс? • Куда девается вся свободная память? • Если я раздаю файлы с диска зачем мне много памяти? • Почему запись быстрее чтения? • Почему перезапустить MySQL тяжелее чем MongoDB? • Почему я могу потерять данные при записи на диск? 4
  • 5.
    Говорим про x86_64 Linux Kernel ≥ 2.6.32 5
  • 6.
    Немного терминов ︎Резидентнаяпамять (resident memory) – объём памяти, которая находится непосредственно в оперативной памяти системы (RAM). Анонимная память (anonymous memory) – память которая не связана ни с каким файлом на диске (without backing store). Page fault – ловушка (trap) обращения к памяти. Штатный механизм при работе с виртуальной памятью. 6
  • 7.
    Работа с памятьючерез страницы Страница – это минимальная единица памяти, с которой происходит работа. Размер страницы 4KB. Существуют Huge Pages – 2MB (не будем рассматривать). 7 Адресное пространство page page page page page 0x0 0xFFFFFFFF … 4KB page
  • 8.
    Процесс работает свиртуальной памятью 8 Адресное пространство процесса Основная память RAM Swap устройство Отображение памяти Виртуальная память Paging/swapping • абстрактная модель; • упрощает разработку; • оставляем работу с настоящей памятью ОС; • позволяет превышать размеры основной памяти.
  • 9.
    Настраиваем О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
  • 10.
    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
  • 11.
    Неравномерное заполнение NUMA Memory Nodes 30GB Управляем выделением памяти: # numactl --interleave all command 11 Node 1 Node 2 56GB
  • 12.
    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
  • 13.
    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
  • 14.
    Read и PageCache 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
  • 15.
    Write и PageCache По умолчанию запись происходит только в 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
  • 16.
    Память процесса Сегменты: • 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
  • 17.
    Как посмотреть •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
  • 18.
    Virtual Memory Area(VMA) Область памяти (virtual memory area VMA) – описывает пространство адресов в памяти процесса (например 08048000-0804c000). Права на области: • Чтение (r); • Запись (w); • Исполнение (e). Области видимости и доступа: • приватные (p); • общие (s). 18
  • 19.
    Смотрим 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
  • 20.
    Выделение памяти 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)
  • 21.
    malloc() и free() glibc malloc() – выделяет анонимную память: • heap – для аллокации маленьких объёмов (≤128KB); • mmap() для остального. free() – освобождает память.
  • 22.
    Пример 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
  • 23.
    mmap() и munmap() 23 mmap area mmap(fd, …) /var/lib/db/index Виртуальная память процесса Диск mmap() – позволяет отображать содержимое файла на адресное пространство процесса. munmap() – освобождает память.
  • 24.
    Флаги mmap() Задаёмвидимость наших изменений: • MAP_PRIVATE и указание файла; • MAP_SHARED и указание файла. Можем явно задать уровень доступа: • PROT_READ; • PROT_WRITE. 24
  • 25.
    На самом делеLinux не выделяет всю запрошенную память сразу. 25
  • 26.
    Page fault (demandpaging) 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 – без обращения на диск.
  • 27.
    Типы Page Fault • Minor – без обращения на диск; • major – с обращением на диск; • invalid – ошибочное обращение (segmentation fault). 27
  • 28.
    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
  • 29.
    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
  • 30.
    Работа с файламии памятью 30
  • 31.
    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
  • 32.
    malloc() и работас файлами • Используем больше памяти. • Копирование в user space – больше CPU и переключений контекста. 32
  • 33.
    mmap и работас файлами 33 Простое отображение в Page Cache. mmap() #0 #1 Page Cache m.log#0 free /bin/ls libc.so m.log#1 mmap area #2
  • 34.
    mmap и minorpage 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
  • 35.
    mmap и majorpage 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. Идём на диск и зачитываем страницу в память.
  • 36.
    mmap и majorpage 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
  • 37.
    mmap() выводы 37 • Позволяет работать с файлами как с памятью. • “Lazy loading”. • Быстрее – меньше системных вызовов и переключений контекста. • Экономит память. • При завершении программы данные остаются в памяти.
  • 38.
    Мониторим память 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
  • 39.
    Работаем с PageCache 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
  • 40.
    Пару слов проreadahead Управлять readahead можно: • readahead(); • madvise(); • posix_fadvise(); • blockdev --report blockdev --setra <value> <device>. 40
  • 41.
    Освобождение памяти (pagereclaiming) Страницы памяти: • unreclaimable; • swappable; • syncable; • discardable. 41
  • 42.
    Источники пополнения freelist 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
  • 43.
    Page Scanning (kswapd) 43 high pages low pages min pages background synchronous time size of available free memory Регулируется vm.min_free_kbytes
  • 44.
    LRU/2 44 referenced tail head Active List head Inactive List tail free page Free List referenced head tail page allocation free pages reclaim
  • 45.
    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
  • 46.
    Out Of MemoryKiller (OOM) Логи: grep -i kill /var/log/messages* Меняем веса (-16 … 15, -17 – выключить): echo “-17” > /proc/<pid>/oom_adj Текущая сумма очков для pid: cat /proc/<pid>/oom_score 0 46
  • 47.
    Memory cgroup Можемограничивать повсякому: • память; • память + swap; • свой OOM; • swappiness. Удобная статистика: # cat memory.stat … inactive_anon 0 active_anon 0 inactive_file 0 active_file 0 unevictable 0 47
  • 48.
    Cgroup page reclaiming • Global reclaiming. • Target reclaiming. 48
  • 49.
    Почитать 49 SystemsPerformance: Enterprise and the Cloud Linux System Programming: Linux Kernel Development Talking Directly to the Kernel and C Library
  • 50.