Ответ 1
Прежде всего, на x86-системах ограничение памяти составляет 2 ГБ, а не 200 МБ. я полагаю
ваша проблема намного сложнее. У вас есть агрессивная фрагментация LOH (крупная куча объекта).
CLR использует разные кучи для малых и больших объектов. Объект большой, если его размер превышает 85 000 байт. LOH - очень разборчивая вещь, она не хочет возвращать неиспользованную память обратно в ОС, и она очень бедна при дефрагментации.
.Net List - это реализация структуры данных ArrayList, она хранит элементы в массиве с фиксированным размером; при заполнении массива создается новый массив с удвоенным размером. Этот непрерывный рост массива с вашим объемом данных - это сценарий "голодания" для LOH.
Таким образом, вы должны использовать индивидуальную структуру данных в соответствии с вашими потребностями. Например. список кусков, причем каждый кусок достаточно мал, чтобы не попасть в LOH. Вот небольшой прототип:
public class ChunkedList
{
private readonly List<float[]> _chunks = new List<float[]>();
private const int ChunkSize = 8000;
private int _count = 0;
public void Add(float item)
{
int chunk = _count / ChunkSize;
int ind = _count % ChunkSize;
if (ind == 0)
{
_chunks.Add(new float[ChunkSize]);
}
_chunks[chunk][ind] = item;
_count ++;
}
public float this[int index]
{
get
{
if(index <0 || index >= _count) throw new IndexOutOfRangeException();
int chunk = index / ChunkSize;
int ind = index % ChunkSize;
return _chunks[chunk][ind];
}
set
{
if(index <0 || index >= _count) throw new IndexOutOfRangeException();
int chunk = index / ChunkSize;
int ind = index % ChunkSize;
_chunks[chunk][ind] = value;
}
}
//other code you require
}
С ChunkSize
= 8000 каждый кусок займет всего 32 000 байт, поэтому он не попадет в LOH. _chunks
попадет в LOH только тогда, когда в коллекции будет около 16 000 кусков, что составляет более 128 миллионов элементов в коллекции (около 500 МБ).
UPD Я провел несколько стресс-тестов для примера выше. ОС - x64, платформа решений - x86. ChunkSize - 20000.
Во-первых:
var list = new ChunkedList();
for (int i = 0; ; i++)
{
list.Add(0.1f);
}
OutOfMemoryException выражается в ~ 324 000 000 элементов
Во-вторых:
public class RawData
{
public string Name;
public ChunkedList Data = new ChunkedList();
}
var list = new List<RawData>();
for (int i = 0;; i++)
{
var raw = new RawData { Name = "Test" + i };
for (int j = 0; j < 20 * 1000 * 1000; j++)
{
raw.Data.Add(0.1f);
}
list.Add(raw);
}
OutOfMemoryException возникает при я = 17, j ~ 12 000 000. 17 экземпляров RawData успешно созданы, 20 миллионов точек данных на каждый, около 352 миллионов точек данных полностью.