Хорошо, так что трудно объяснить большие понятия в 400 символов или меньше, поэтому я думаю, что я просто вызываю больше путаницы в разделе комментариев. Кроме того, я думаю, что мы достаточно близко относимся к «ответ», как вы, вероятно, получите.
Конструктор по умолчанию MemoryStream
по существу устанавливает начальный размер равным 0. В действительности, начальный размер устанавливается где-то около 256, но поскольку начальный размер является главным образом ориентиром, и на самом деле он не утверждает это пространство до тех пор, пока его необходимо, оно начинается с 0.
Каждый раз, когда вы пишете в поток, он проверяет, сколько написано в сравнении с остальным размером массива буфера. Если он не может соответствовать записи, он создает новый больший буферный массив и копирует в него старый буферный массив. Таким образом, установка начального размера может помочь в том, что вы начинаете с большего массива начального буфера, и вам может не понадобиться вырастить этот буфер. У вас есть может иметь больше шансов получить непрерывный блок памяти, который я объясню важность немного, но это на самом деле тоже работает против вас. Если вам нужен только 1 МБ для файла, но вы инициализируетесь с 100 МБ и, то нет 100 Мб непрерывной памяти, вы получите OutOfMemoryException
, хотя может быть 1 МБ непрерывной памяти.
Независимо от того, инициализированы ли вы или нет, остаются некоторые непреложные факты. Во-первых, MemoryStream
требует непрерывной памяти. Даже если у вас есть технически доступная память в системе, возможно, у вас может не быть больших блоков доступной памяти. Другими словами, если у вас есть 4 ГБ, но все фрагментировано, даже попытка создать поток 1 ГБ в памяти может потерпеть неудачу, просто потому, что он не может зарезервировать 1 ГБ смежных памяти. Очевидно, чем больше файл, который вы связываете для создания в памяти, тем больше вероятность того, что вы столкнетесь с этой проблемой. По этой причине я бы сказал, что вам не повезло, не увеличивая объем оперативной памяти. С 8 ГБ и, вероятно, только 4-6 ГБ, фактически доступными для IIS, а затем разделить между рабочими процессами и потоками, вероятность того, что вы сможете требовать 25% или около того доступной ОЗУ в качестве непрерывного пространства, маловероятна.
Следующий непреложный факт может быть или не быть релевантным, но поскольку вы не указали, я расскажу об этом. Если ваше веб-приложение развернуто как 32-разрядное, у вас будет жесткий предел в 2 ГБ для любого объекта, то есть MemoryStream
никогда не сможет разместить более 2 ГБ (на самом деле около 1,3-1,6 ГБ.NET-код потребляет часть этого адресного пространства), и любая попытка сделать это приведет к OutOfMemoryException
, даже если у вас было какое-то нелепое количество оперативной памяти в системе, например, 1TB +. Если ваше приложение является 64-битным, это, скорее всего, проблема, поскольку вы можете адресовать тонну больше памяти, предполагая, что она скомпилирована должным образом. Вы, должно быть, очень пытаетесь это испортить, так что с вами все будет в порядке.
И, наконец, многократная запись может также вызвать проблему. Как я уже говорил ранее, массив буфера изменяет размер (при необходимости) в ответ на запись. Каждый раз, когда он изменяет размер, новый буферный массив должен также быть в состоянии разместить в смежном адресном пространстве. В результате множественные изменения размеров могут привести к тому, что вы столкнетесь с OutOfMemoryException
, которые вы бы не ударили, если бы вы написали все данные с самого начала. Здесь инициализация MemoryStream
может быть полезна, но, как я уже говорил, это также обоюдоострый меч, так как ваш начальный размер буфера может быть слишком велик, чтобы начать, и вы получите исключение, где у вас может не быть одного позволяя ему расти органично. Длинные и короткие, старайтесь писать все в поток за один раз, а не по частям.
Хотя вы не указали точную проблему, с которой вы сталкиваетесь, на основе тегов вашего вопроса, я предполагаю, что у вас закончилась нехватка памяти. Для этого нет решения, кроме того, что на вашем сервере больше места. Не существует встроенного ограничения на загрузку, но если вы создаете что-то в памяти, очевидно, оно не может быть больше, чем доступная память системы. –
Стоит отметить, что вам также потребуется учитывать несколько запросов. Например, если вы создаете файл размером 1 ГБ, добавление 1 ГБ дополнительной памяти помогает только одному запросу. Если два человека пытаются получить доступ к тому же действию, которое создает этот 1GB-файл, тогда вам понадобится 2 ГБ ОЗУ для удовлетворения обоих запросов. Кэширование созданного файла в файловой системе помогло бы, поскольку вам понадобится только память для первоначального создания, но вы должны убедиться, что у вас много запаса выше среднего размера файла. –
Я запросил больше памяти у руководства (но я не задерживаю дыхание ...) У него уже 8 концертов. – user2996466