Я заметил, что в моем приложении заканчивается память быстрее, чем нужно. Он создает много байтовых массивов по несколько мегабайт каждый. Однако, когда я смотрел на использование памяти с помощью vmmap, появляется, что .NET выделяет гораздо больше, чем необходимо для каждого буфера. Если быть точным, при распределении буфера в 9 мегабайт,.NET создает кучу 16 мегабайт. Оставшиеся 7 мегабайт нельзя использовать для создания другого буфера в 9 мегабайт, поэтому .NET создает еще 16 мегабайт. Таким образом, каждый буфер 9 МБ отнимает 7 МБ адресного пространства!
Вот пример программы, которая генерирует исключение OutOfMemoryException после выделения 106 буферов в 32-битном .NET 4:
using System.Collections.Generic;
namespace CSharpMemoryAllocationTest
{
class Program
{
static void Main(string[] args)
{
var buffers = new List<byte[]>();
for (int i = 0; i < 130; ++i)
{
buffers.Add(new byte[9 * 1000 * 1024]);
}
}
}
}
Обратите внимание, что вы можете увеличить размер массива до 16 * 1000 * 1024 и по-прежнему выделять столько же буферов, пока не исчерпаете память.
VMMap показывает это:
Также обратите внимание на то, что разница между общим размером управляемой кучи и общим значением Commited size составляет почти 100%. (1737MB против 946MB).
Есть ли надежный способ решения этой проблемы в .NET, то есть я могу принудить среду выполнения к распределению не более того, что мне действительно нужно, или, может быть, намного более крупным управляемым кучам, которые могут использоваться для нескольких смежных буферов?