Ответ 1
Вы можете положиться на этот метод, работающий корректно, это исключение очень, которое может совершить поездку в 32-битном процессе, когда вы запрашиваете 250 мегабайт. Это становится трудно получить, когда программа работает некоторое время.
Программа никогда не сбой с OOM, потому что вы потребляли все доступное адресное пространство виртуальной памяти. Он выходит из строя, потому что в адресном пространстве нет дыры, достаточно большой, чтобы соответствовать распределению. Ваш код требует отверстия достаточно большого, чтобы выделить 250 мегабайт в одном gulp. Когда вы не получите исключение, вы можете быть уверены, что это распределение не будет выполнено.
Но 250 мегабайт довольно много, это действительно большой массив. И, скорее всего, не удастся из-за проблемы, называемой "фрагментация адресного пространства". Другими словами, программа, как правило, начинается с нескольких очень больших отверстий, самая большая около 600 мегабайт. Доступны отверстия между распределениями, предназначенными для хранения кода и данных, которые используются средой выполнения .NET и неуправляемыми библиотеками Windows. Поскольку программа выделяет больше памяти, эти отверстия становятся меньше. Вероятно, он выпустит некоторую память, но это не воспроизводит большую дыру. Обычно вы получаете две дыры, примерно половину от размера оригинала, с расположением где-то посередине, которое разрезает исходное большое отверстие на два.
Это называется фрагментацией, 32-разрядный процесс, который выделяет и освобождает много памяти, заканчивает фрагментацию адресного пространства виртуальной памяти, поэтому самое большое отверстие, которое все еще доступно через некоторое время, становится меньше, около 90 мегабайт довольно типично. Спрос на 250 мегабайт почти гарантированно провалится. Вам нужно будет опуститься ниже.
Вы, без сомнения, ожидали, что он будет работать по-другому, гарантируя, что сумма ассигнований, суммирующая до 250 мегабайт, будет работать. Однако это не так, как работает MemoryFailPoint, оно проверяет только максимально возможное распределение. Излишне говорить, что, возможно, это делает его менее полезным. В противном случае я сочувствую программистам на платформе .NET, чтобы заставить его работать так, как нам бы хотелось, и он дорог, и фактически не может гарантировать гарантии, поскольку размер распределения имеет наибольшее значение.
Виртуальная память - это богатый ресурс, который невероятно дешев. Но приблизиться к потреблению - это очень хлопотно. Как только вы потребляете гигабайт, тогда OOM, поражающий наугад, начинает становиться вероятным. Не забывайте про легкое исправление этой проблемы, вы работаете в 64-битной операционной системе. Таким образом, простое изменение целевой платформы EXE на AnyCPU дает вам gobs и gobs виртуального адресного пространства. Зависит от выпуска ОС, но возможен терабайт. Это все еще фрагменты, но вам просто все равно, дыры огромны.
Последнее, но не менее важное, видимое в комментариях, эта проблема имеет ничего для работы с ОЗУ. Виртуальная память совершенно не связана с тем, сколько у вас RAM. Задача операционной системы состоит в том, чтобы сопоставлять адреса виртуальной памяти с физическими адресами в ОЗУ, она делает это динамически. Доступ к ячейке памяти может привести к сбою в ошибке страницы, ОС будет выделять ОЗУ для этой страницы. И происходит обратное: ОС будет отформатировать RAM для страницы, когда она понадобится в другом месте. Вы никогда не можете выбежать из ОЗУ, машина замедлит сканирование до того, как это произойдет. Утилита VMMap SysInternals приятно видеть, как выглядит ваше виртуальное адресное пространство вашей программы, хотя вы склонны утонуть в информации для большого процесса.