Linux более совершенный эвристический
В статье о пере-фиксации из документа ядра просто упоминается, что режим сверх-фиксации 0 основан на эвристической обработке сверх-фиксации. Это не обрисовывает в общих чертах эвристику, вовлеченную.
Может ли кто-то пролить свет на фактическую эвристику? Любая соответствующая ссылка на исходники ядра тоже работает!
1 ответ
На самом деле, документация ядра по учету overcommit имеет некоторые детали: https://www.kernel.org/doc/Documentation/vm/overcommit-accounting
Ядро Linux поддерживает следующие режимы обработки overcommit
0 - Эвристическая обработка overcommit.
Очевидные нарушения адресного пространства отклоняются. Используется для типичной системы. Это обеспечивает серьезное сбои при распределении, позволяя при избыточной загрузке уменьшить использование подкачки. В этом режиме root может выделить немного больше памяти. Это по умолчанию.
Также Документация / sysctl / vm.txt
overcommit_memory: это значение содержит флаг, который разрешает чрезмерное использование памяти.
Когда этот флаг равен 0, ядро пытается оценить объем свободной памяти, когда пользовательское пространство запрашивает больше памяти...См. Documentation / vm / overcommit-accounting и mm/mmap.c::__vm_enough_memory() для получения дополнительной информации.
Также, man 5 proc
:
/proc/sys/vm/overcommit_memory
Этот файл содержит режим учета виртуальной памяти ядра. Значения:0: heuristic overcommit (this is the default) 1: always overcommit, never check 2: always check, never overcommit
В режиме 0 вызовы
mmap(2)
сMAP_NORESERVE
не проверяются, и проверка по умолчанию очень слабая, что приводит к риску получения процесса "OOM-kill".
Таким образом, очень большие выделения отключаются эвристикой, но иногда приложение может выделить больше виртуальной памяти, чем размер физической памяти в системе, если оно не использует все это. С MAP_NORESERVE
количество mmapable памяти может быть выше.
Параметр " Политика overcommit устанавливается через sysctl` vm.overcommit_memory ' ", поэтому мы можем узнать, как это реализовано в исходном коде: http://lxr.free-electrons.com/ident?v=4.4;i=sysctl_overcommit_memory, определенный в строке 112 мм / mmap.c
112 int sysctl_overcommit_memory __read_mostly = OVERCOMMIT_GUESS; /* heuristic overcommit */
и постоянный OVERCOMMIT_GUESS
(определено в linux / mman.h) фактически используется только в строке 170 файла mm / mmap.c, это реализация эвристики:
138 /*
139 * Check that a process has enough memory to allocate a new virtual
140 * mapping. 0 means there is enough memory for the allocation to
141 * succeed and -ENOMEM implies there is not.
142 *
143 * We currently support three overcommit policies, which are set via the
144 * vm.overcommit_memory sysctl. See Documentation/vm/overcommit-accounting
145 *
146 * Strict overcommit modes added 2002 Feb 26 by Alan Cox.
147 * Additional code 2002 Jul 20 by Robert Love.
148 *
149 * cap_sys_admin is 1 if the process has admin privileges, 0 otherwise.
150 *
151 * Note this is a helper function intended to be used by LSMs which
152 * wish to use this logic.
153 */
154 int __vm_enough_memory(struct mm_struct *mm, long pages, int cap_sys_admin)
...
170 if (sysctl_overcommit_memory == OVERCOMMIT_GUESS) {
171 free = global_page_state(NR_FREE_PAGES);
172 free += global_page_state(NR_FILE_PAGES);
173
174 /*
175 * shmem pages shouldn't be counted as free in this
176 * case, they can't be purged, only swapped out, and
177 * that won't affect the overall amount of available
178 * memory in the system.
179 */
180 free -= global_page_state(NR_SHMEM);
181
182 free += get_nr_swap_pages();
183
184 /*
185 * Any slabs which are created with the
186 * SLAB_RECLAIM_ACCOUNT flag claim to have contents
187 * which are reclaimable, under pressure. The dentry
188 * cache and most inode caches should fall into this
189 */
190 free += global_page_state(NR_SLAB_RECLAIMABLE);
191
192 /*
193 * Leave reserved pages. The pages are not for anonymous pages.
194 */
195 if (free <= totalreserve_pages)
196 goto error;
197 else
198 free -= totalreserve_pages;
199
200 /*
201 * Reserve some for root
202 */
203 if (!cap_sys_admin)
204 free -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);
205
206 if (free > pages)
207 return 0;
208
209 goto error;
210 }
Итак, эвристика - это способ оценить, сколько страниц физической памяти используется сейчас (free
), когда обрабатывается запрос дополнительной памяти (приложения запрашивают pages
страницы).
При всегда включенном overcommit ("1") эта функция всегда возвращает 0 ("достаточно памяти для этого запроса")
164 /*
165 * Sometimes we want to use more memory than we have
166 */
167 if (sysctl_overcommit_memory == OVERCOMMIT_ALWAYS)
168 return 0;
Без этой эвристики по умолчанию в режиме "2" ядро будет пытаться учесть запрошенные pages
страницы, чтобы получить новые Committed_AS
(от /proc/meminfo
):
162 vm_acct_memory(pages);
...
на самом деле это просто приращение vm_committed_as
- __percpu_counter_add(&vm_committed_as, pages, vm_committed_as_batch);
212 allowed = vm_commit_limit();
Некоторая магия здесь:
401 /*
402 * Committed memory limit enforced when OVERCOMMIT_NEVER policy is used
403 */
404 unsigned long vm_commit_limit(void)
405 {
406 unsigned long allowed;
407
408 if (sysctl_overcommit_kbytes)
409 allowed = sysctl_overcommit_kbytes >> (PAGE_SHIFT - 10);
410 else
411 allowed = ((totalram_pages - hugetlb_total_pages())
412 * sysctl_overcommit_ratio / 100);
413 allowed += total_swap_pages;
414
415 return allowed;
416 }
417
Так, allowed
устанавливается либо как килобайт в vm.overcommit_kbytes
sysctl или как vm.overcommit_ratio
в процентах от физической памяти, плюс размеры подкачки.
213 /*
214 * Reserve some for root
215 */
216 if (!cap_sys_admin)
217 allowed -= sysctl_admin_reserve_kbytes >> (PAGE_SHIFT - 10);
Разрешить некоторый объем памяти только для root (Page_shift равен 12 для здорового человека, page_shift-10 - это просто преобразование из килобайта в число страниц).
218
219 /*
220 * Don't let a single process grow so big a user can't recover
221 */
222 if (mm) {
223 reserve = sysctl_user_reserve_kbytes >> (PAGE_SHIFT - 10);
224 allowed -= min_t(long, mm->total_vm / 32, reserve);
225 }
226
227 if (percpu_counter_read_positive(&vm_committed_as) < allowed)
228 return 0;
Если после учета запроса все пользовательское пространство по-прежнему имеет выделенный объем памяти меньше разрешенного, выделите его. В другом случае отклоните запрос (и отмените запрос).
229 error:
230 vm_unacct_memory(pages);
231
232 return -ENOMEM;
Другими словами, как указано в "Ядре Linux. Некоторые замечания по ядру Linux", 2003-02-01, Andries Brouwer, 9. Memory, 9.6 Overcommit и OOM - https://www.win.tue.nl/~aeb/linux/lk/lk-9.html:
Идти в правильном направлении
Начиная с 2.5.30 значения:
0
(по умолчанию): как и раньше: угадайте, насколько чрезмерное ограничение является разумным,1
никогда не отказывайся от malloc (),2
: будьте точны в отношении чрезмерной передачи - никогда не фиксируйте виртуальное адресное пространство больше, чем пространство подкачки плюс дробьovercommit_ratio
физической памяти.
Таким образом, "2" - это точное вычисление объема памяти, использованного после запроса, а "0" - эвристическая оценка.