Какой самый большой объем памяти я могу выделить на своем MacBook Pro?

Я пытаюсь выяснить, сколько памяти я могу выделить, прежде чем выделение не удастся.

Этот простой код C ++ выделяет буфер (размером 1024 байта), назначает последние пять символов буфера, сообщает, а затем удаляет буфер. Затем он удваивает размер буфера и повторяется до тех пор, пока не выйдет из строя.

Если я чего-то не упускаю, код может выделить до 65 терабайт памяти, прежде чем он выйдет из строя на моем MacBook Pro. Это вообще возможно? Как он может выделить намного больше памяти, чем у меня на машине? Должно быть, я упускаю что-то простое.

int main(int argc, char *argv[])
{
        long long size=1024;
        long cnt=0;
        while (true)
        {
                char *buffer = new char[size];
                // Assume the alloc succeeded. We are looking for the failure after all.

                // Try to write to the allocated memory, may fail
                buffer[size-5] = 'T';
                buffer[size-4] = 'e';
                buffer[size-3] = 's';
                buffer[size-2] = 't';
                buffer[size-1] = '\0';

                // report
                if (cnt<10)
                        cout << "size[" << cnt << "]: " << (size/1024.) << "Kb ";
                else if (cnt<20)
                        cout << "size[" << cnt << "]: " << (size/1024./1024.) << "Mb ";
                else
                        cout << "size[" << cnt << "]: " << (size/1024./1024./1024.) << "Gi ";
                cout << "addr: 0x" << (long)buffer << " ";
                cout << "str: " << &buffer[size-5] << "\n";

                // cleanup
                delete [] buffer;

                // double size and continue
                size *= 2;
                cnt++;
        }
        return 0;
}

person Thomas Jay Rush    schedule 30.12.2016    source источник
comment
размещение переменных в оперативной памяти или на жестком диске?   -  person Raindrop7    schedule 31.12.2016
comment
Кстати: если вы действительно пытаетесь определить фактический максимум, который вы можете выделить, у вас должен быть дополнительный цикл, используемый после первого сбоя, где вы уменьшаете сумму, добавляемую к вашему запросу на выделение, каждый раз в два раза, пока вы не увеличите минимум, который вы хотите проверить. Например: запрос на 512 ГБ в порядке, запрос на 1024 ГБ не выполняется, затем запрос (512 ГБ + 256 ГБ) = 768 ГБ (если все в порядке, то (768 ГБ + 128 ГБ) = 896 ГБ, в случае неудачи попробуйте (512 ГБ + 128 ГБ) = 640 ГБ) и т. Д.   -  person Makyen♦    schedule 31.12.2016
comment
macbook pro или нет здесь не имеет значения, вам не нужно указывать это в заголовке. Выделение большего объема памяти, чем существует, с помощью malloc, максимальный объем памяти, который может выделить malloc   -  person phuclv    schedule 31.12.2016
comment
Вы можете поверить в миф о том, что память - это ОЗУ. Память - это не ОЗУ. Память - это абстракция способности хранить данные и извлекать их, и эта абстракция может быть реализована с помощью множества различных видов оборудования. ОЗУ - это всего лишь быстрое и удобное решение. Вам лучше думать о памяти как о дисковом пространстве, а ОЗУ как о кеш-памяти, ускоряющем доступ к диску, потому что в наши дни это то, что есть.   -  person Eric Lippert    schedule 31.12.2016


Ответы (3)


Когда вы запрашиваете память, операционная система оставляет за собой право фактически не отдавать вам эту память, пока вы не воспользуетесь ею.

Вот что здесь происходит: вы используете только 5 байтов. Мой ZX81 из 80-х справился с этим.

person Bathsheba    schedule 30.12.2016
comment
Я им пользуюсь. Я записываю данные в последние пять символов буфера и затем распечатываю их. - person Thomas Jay Rush; 30.12.2016
comment
Так что, операционная система умнее, чем вы думаете. Вам не кажется, что MacBook Pro просто красив? - person Bathsheba; 30.12.2016
comment
Ой. Значит, если бы я написал для каждого символа в каждом буфере, он бы отказал намного раньше? Ты это говоришь? - person Thomas Jay Rush; 30.12.2016
comment
Ага. Хорошо созданная ОС вернет вам память блоками; часто называемые страницами. - person Bathsheba; 30.12.2016
comment
Понятно. Спасибо. Я знал, что, должно быть, что-то упустил. - person Thomas Jay Rush; 30.12.2016
comment
google: // память + чрезмерная нагрузка - person n. 1.8e9-where's-my-share m.; 30.12.2016
comment
@ThomasJayRush: использовать его означает писать на него везде или, по крайней мере, на каждую страницу (обычно 4 или 8 КБ). В противном случае ОС просто не предоставляет часть памяти или ее часть. - person Zbynek Vyskovsky - kvr000; 30.12.2016
comment
Я изменил код для записи в каждую 512-байтовую ячейку памяти в каждом буфере. Притормаживает существенно, но все равно выделяет не менее 32 Гиг. У компьютера только 4 ГБ памяти, но я полагаю, что он использует пространство подкачки. Я устал ждать, пока он выйдет из строя, а 32 гигабайта - это намного больше, чем мне нужно, так что спасибо за быстрые ответы. Я выберу твой ответ, как только смогу. - person Thomas Jay Rush; 30.12.2016
comment
В вашем ZX81 не было виртуальной памяти? Это ключ к выделению гораздо большего, чем физическое + пространство подкачки, но при этом требуется только одна страница физической ОЗУ для одной страницы, которую вы испачкали. Остальные страницы остаются доступными только для чтения физической нулевой странице. - person Peter Cordes; 31.12.2016
comment
@Bathsheba - система виртуальной памяти, которая делает избыточную фиксацию, - это просто сбой во время выполнения, ожидающий своего появления в случайное время. Помещение его в симпатичный футляр с завышенной ценой не решает этой проблемы! - person alephzero; 31.12.2016
comment
Но операционная система немедленно предоставляет вам адресное пространство, чего не мог бы сделать ваш ZX81. Я думаю, что ваш ответ можно улучшить, кратко обсудив адресное пространство, страницы ОЗУ и своп. - person derobert; 31.12.2016

MacOS X, как и почти любая современная операционная система, использует «отложенное выделение памяти» для памяти. Когда вы вызываете new, ОС фактически не выделяет памяти. Он просто отмечает, что вашей программе требуется определенный объем памяти, и эта область памяти, которую вы хотите, начинается с определенного адреса. Память фактически выделяется только тогда, когда ваша программа пытается ее использовать.

Кроме того, память распределяется в единицах, называемых «страницами». Я считаю, что MacOS X использует страницы размером 4 КБ, поэтому, когда ваша программа записывает в конец буфера, ОС дает вам 4096 байт там, сохраняя при этом остальную часть буфера просто как примечание «вашей программе нужна эта память».

Что касается того, почему вы достигли предела в 64 терабайта, это потому, что текущие процессоры x86-64 используют 48-битную адресацию. Это дает 256 ТБ адресного пространства, которое равномерно распределяется между операционной системой и вашей программой. Удвоение выделения 64 ТБ точно поместится в половине адресного пространства вашей программы, равном 128 ТБ, за исключением того, что программа уже занимает его немного.

person Mark    schedule 30.12.2016
comment
Для чего они используют дополнительные 16 бит адреса? - person tbodt; 31.12.2016
comment
@tbodt - Нет. По сути, это теоретически 64-битное адресное пространство, но по причинам компоновки старшие 16 бит не связаны, потому что чип в любом случае физически не может поддерживать такой объем памяти. Это упрощает кремниевую конструкцию, потому что у вас нет этих огромных участков шины, которые ходят повсюду, но на самом деле ничего не делают. - person Fake Name; 31.12.2016
comment
Обратите внимание, что Windows также выполняет отложенное выделение, но не выполняет избыточное выделение, поэтому в Windows вы не должны иметь возможность выделять больше, чем ваша общая RAM + пространство подкачки - память уже используется. - person user253751; 31.12.2016
comment
Я не думаю, что какие-либо ОС по умолчанию используют огромные страницы (2 МБ или 1 ГБ для x86-64) (за исключением таких вещей, как прозрачные огромные страницы Linux), так что да, нормальные страницы 4kiB x86 - безопасное предположение. Я опубликовал ответ с более подробной информацией о том, как работает ленивое размещение копирования при записи. - person Peter Cordes; 31.12.2016

Виртуальная память - это ключ к выделению большего адресного пространства, чем у вас есть физической RAM + пространство подкачки.

malloc использует системный вызов mmap(MAP_ANONYMOUS) для получения страниц из ОС. (Предполагая, что OS X работает как Linux, поскольку они обе ОС POSIX). Все эти страницы копируются при записи и сопоставляются с одной физической нулевой страницей. то есть все они читаются как ноль, только с ошибкой TLB (без ошибки страницы и без выделения физической RAM). Размер страницы x86 составляет 4 КБ. (Я не говорю об огромных страницах, потому что они здесь не актуальны).

Запись на любую из этих страниц вызывает программную ошибку страницы для ядра, чтобы обработать копирование при записи. Ядро выделяет обнуленную страницу физической памяти и перенаправляет эту виртуальную страницу для поддержки физической страницы. При возврате из ошибки страницы, хранилище повторно запускается и на этот раз успешно.

Итак, выделив 64 ТиБ и сохранив до конца 5 байтов, вы использовали одну дополнительную страницу физической памяти. (И добавил запись в бухгалтерские данные malloc, но она, вероятно, уже была выделена и на грязной странице. В аналогичном вопросе о нескольких крошечных выделениях бухгалтерские данные malloc в конечном итоге израсходовали все пространство).

Если вы действительно загрязнили больше страниц, чем в системе было RAM + swap, у ядра возникли бы проблемы, потому что malloc уже слишком поздно возвращать NULL. Это называется "overcommit", и некоторые операционные системы включают его по умолчанию, а другие - нет. В Linux это настраивается.


Как объясняет Марк, вы выдели 64 ТиБ, потому что текущие реализации x86-64 поддерживают только 48-битные виртуальные адреса. Старшие 16 битов должны быть копиями 47-го бита (т. Е. Адрес является каноническим только в том случае, если 64-битное значение является знаковым расширением младших 48 бит).

Это требование не позволяет программам делать что-нибудь «умное» с старшими битами, а затем нарушать работу будущего оборудования, которое действительно поддерживает еще большие виртуальные адресные пространства.

person Peter Cordes    schedule 31.12.2016