Что происходит, когда оперативная память заканчивается в C#?


Я не специалист по компьютерам, поэтому позвольте мне попытаться сформулировать этот вопрос немного более конкретно:

Я делаю некоторые научные вычисления, и вычисления иногда требуют много памяти для хранения их результатов. Несколько дней назад у меня был выходной файл, который занял 4 ГБ на жестком диске, но у меня есть этот объем оперативной памяти. Итак:
  • Как работает CLR (или это что-то другое?) имеет дело с памятью, когда программа, которую вы запускаете, выделяет больше памяти, чем доступно в компьютере? Создает ли он какую-то подкачку в HD? (Я знаю, что это может замедлить мою программу, но меня интересует только проблема памяти)
  • зависит ли это от ОС, скажем, если я работаю с MONO на linux или с VS на Windows?

Заранее спасибо!

3 6

3 ответа:

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

Это в корне отличается от того, как большинство людей думают об этом, но я нахожу, что это помогает. Оперативная память-это просто оптимизация производительности; реальный предел того, сколько памяти вы можете выделить, - это доступное дисковое пространство.

Из конечно, все гораздо сложнее. В 32-битных операционных системах каждый процесс получает 2 миллиарда байт адресного пространства пользователя . (И то же самое для адресного пространства ядра, но давайте проигнорируем это.) Каждая страница памяти, к которой вы можете получить доступ, будь то в оперативной памяти или на диске, должна находиться в этом адресном пространстве. Вы можете выделить более 2 миллиардов байт, без проблем. Но вы можете адресовать только 2 ГБ его за один раз. Если у вас выделено 10 ГБ, то по крайней мере 8 ГБ из них не будут сопоставлены в адресное пространство. В этом случае вам нужноразомкнуть что-то еще, а затем сопоставить то, что вы хотите, в адресное пространство, чтобы добраться до него.

Более того, множество вещей должно быть внепрерывном адресном пространстве. Например, если у вас есть стек размером 1 МБ, то в адресном пространстве должен быть миллион непрерывных байт.

Когда у людей "заканчивается память", у них не заканчивается оперативная память; Оперативная память-это просто быстрый кэш на диске. И это не так дисковое пространство на исходе, его там предостаточно. Они почти всегда находятся в ситуации, когда нет достаточного смежного адресного пространства для удовлетворения спроса.

Менеджер памяти CLR не реализует эти причудливые стратегии map-and-unmap для вас; в основном, вы получаете адресное пространство 2 ГБ, и все. Если вы хотите сделать что-то необычное, скажем, с файлами, сопоставленными с памятью, это зависит от вас, чтобы написать код для управления памятью самостоятельно.

Если вы выделяете больше памяти, чем физически существует, да, пространство подкачки будет использоваться.

Если вы выделили больше памяти, чем можно адресовать, произойдет OutOfMemoryException.

Не уверен насчет Mono, но я бы предположил, что это зависит от времени выполнения и будет вести себя примерно так же (недостаточно физической памяти вызовет подкачку, слишком много выделенной вызовет исключение).

Время выполнения просто запрашивает у операционной системы больше памяти. Операционная система обрабатывает подкачку существующего содержимого памяти на диск и в противном случае обменивает вещи вокруг, чтобы создать больше свободной физической памяти, если это необходимо. То же самое происходит здесь для управляемых программ C#/.NET, как и для обычных, неуправляемых программ.

Единственное отличие в мире управляемых приложений заключается в том, что время выполнения .NET накладывает некоторые накладные расходы на память, тем самым ограничивая общий объем память, которая фактически доступна для вашего приложения. Например, сборщику мусора требуется некоторое пространство памяти для выполнения своей работы.

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