Можете ли вы использовать List <List <struct>, чтобы обойти ограничение объекта 2gb?

Я сталкиваюсь с ограничением объекта 2gb в С# (это относится даже к 64-битным по какой-то досадной причине) с большой коллекцией структур (всего размером 4,2 гигабайта).

Теперь очевидно, что использование List даст мне список размера 4.2gb, который даст или возьмет, но будет использовать список, состоящий из меньших списков, которые, в свою очередь, содержат часть структур, позволяют мне перескакивать этот предел?

Мое рассуждение заключается в том, что в CLR ограничивается только жестко запрограммированный предел, который мешает мне создать экземпляр объекта 9gig на моей 64-битной платформе и полностью не связан с системными ресурсами. Также списки и массивы являются ссылочными типами, поэтому список, содержащий списки, будет содержать только ссылки на каждый список. Поэтому ни один объект не превышает ограничение размера.

Есть ли причина, почему это не сработает? Я бы попробовал это сам прямо сейчас, но у меня нет профайлера памяти для проверки.

Ответы

Ответ 1

Теперь очевидно, что использование List даст мне список размера 4.2gb, который даст или возьмет, но будет использовать список, состоящий из меньших списков, которые, в свою очередь, содержат часть структур, позволяют мне перескакивать этот предел?

Да - хотя, если вы пытаетесь обойти этот предел, я бы подумал об использовании массивов самостоятельно, вместо того чтобы позволить классу List<T> управлять массивом.

Ограничение единичного объекта 2gb в CLR - это именно тот экземпляр объекта. Когда вы создаете массив структуры (который List<T> использует внутренне), весь массив является "одним экземпляром объекта" в среде CLR. Однако, используя массив List<List<T>> или jagged, каждый внутренний список/массив представляет собой отдельный объект, который позволяет эффективно иметь любой желаемый размер объекта.

Команда CLR фактически сообщила об этом и предоставила образец BigArray<T>, который действует как один List<T>, но внутреннее управление блоком для тебя. Это еще один вариант для получения списков > 2gb.

Обратите внимание, что .NET 4.5 будет иметь возможность предоставлять объекты размером более 2 Гб на x64, но это будет то, что вы должны явно указать на наличие.

Ответ 2

В List хранятся ссылки, которые составляют 4 или 8 байтов, в зависимости от того, работаете ли вы в 32-разрядном или 64-битном режиме, поэтому, если вы ссылаетесь на объект 2GB, который не увеличит фактический размер List до 2 ГБ, но это только увеличило бы его на количество байтов, которые необходимо ссылаться на этот объект.

Это позволит вам ссылаться на миллионы объектов, и каждый объект может быть 2 ГБ. Если у вас есть 4 объекта в List, и каждый из них имеет 2 ГБ, то у вас есть объекты на 8 ГБ, на которые ссылается List, но объект List использовал бы только лишний 4 * 8 = 32 байтов.

Число ссылок, которые вы можете удерживать на 32-битной машине до того, как List достигнет предела 2 ГБ, составляет 536,87 миллиона, на 64-битной машине - 268,43 миллиона.

536 миллионов ссылок * 2 GB = МНОГО ДАННЫХ!

P.S. Рид отметил, что это верно для ссылочных типов, но не для типов значений. Поэтому, если вы держите типы значений, тогда ваш метод обхода является действительным. Подробнее см. Ниже.

Ответ 4

В версиях .NET до 4.5 максимальный размер объекта составляет 2 ГБ. Начиная с версии 4.5 вы можете выделять более крупные объекты, если включена gcAllowVeryLargeObjects. Обратите внимание, что ограничение для string не влияет, но "массивы" также должны охватывать "списки", поскольку списки поддерживаются массивами.