По какой-то причине наша система начинает подкачку (активно используемой памяти) примерно с 60 ГБ используемой памяти. (см. правку ниже, кажется, что использование ввода-вывода и дискового кэша, даже для ранее запущенных процессов, имеет эффект) Отключение (swapoff-a
) для тестирования приводит к bad_alloc один раз (я предполагаю, потому что в то время было больше процессов, также использующих память), но также работал над ускорением моей программы более чем в 10 раз.
Это воспроизводит проблему (без других важных процессов, выполняющих EDIT: см. Ниже, это происходит только в том случае, если незадолго до этого выполнялся интенсивный процесс ввода-вывода):
#include <cstdio>
#include <vector>
int main() {
size_t bytes = size_t(80) * 1024 * 1024 * 1024; // 80GB
size_t* data = new size_t[bytes / sizeof(size_t)];
for (size_t i = 0; i < bytes / sizeof(size_t); ++i) {
data[i] = i;
}
for (;;) {}
}
Приблизительно при 60 ГБ используемой памяти система начинает подкачку, и загрузка ЦП опускается ниже 100% (потому что сейчас процесс привязан к вводу-выводу, я думаю).
Система - Ubuntu 14.04, 64-битная:
Linux ... 3.13.0-77-generic #121-Ubuntu SMP Wed Jan 20 10:50:42 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
Как только точка будет достигнута, вот что дает мне бесплатный -m:
total used free shared buff/cache available
Mem: 96671 55504 358 60 40808 40478
Swap: 47679 19366 28313
Проблема сохраняется с swappiness = 1 (если что-то с интенсивным вводом-выводом только что было запущено, и особенно для моего фактического виновника (не приведенного выше кода), который выполняет и то, и другое, много операций ввода-вывода и использует много памяти. Если было мало или нет Ввод-вывод в последнее время, программа выше выделяет всю память и не меняет местами!
Проблема исчезнет, если в течение длительного времени не было ничего интенсивного ввода-вывода. Кажется, что ОС каким-то образом заставляет мое приложение менять местами, потому что считает дисковый кеш более ценным - даже при очень низком уровне подкачки. Я не понимаю этого поведения, потому что память дискового кеша должна быть такой же хорошей, как и свободная память, и, безусловно, не запускать подкачку в запущенном процессе.
Изначально моя проблема возникла в приложении, которое читает большие файлы и использует много памяти. Впоследствии он сохраняется в приведенном выше примере кода, в котором вообще нет ввода-вывода. Наконец, когда я позже запускаю пример кода, подкачки не происходит.
Проверьте vmstat
чтобы увидеть si
, so
(swap in / out) фактически заполняет любой своп. даже если для swappiness установлено значение 0, swap может выделить swap.
64 ГБ кажется пределом для 32-битной Ubuntu с поддержкой PAE: https://help.ubuntu.com/community/32bit_and_64bit
32-разрядный компьютер имеет размер слова 32 бита, что теоретически ограничивает объем памяти до 4 ГБ. Этот барьер был расширен за счет использования «расширения физического адреса» (или PAE), которое увеличивает лимит до 64 ГБ, хотя доступ к памяти выше 4 ГБ будет немного медленнее.