2009-07-06 1 views
38

Как я понимаю, ограничение на 2 ГБ для отдельных экземпляров в .NET. Я не обращал на это большого внимания, так как до сих пор я работал над 32-разрядной ОС. На 32, но это более или менее искусственное ограничение в любом случае. Однако я был очень удивлен, узнав, что this limitation also applies on 64 bit .NET.Отдельные объекты по-прежнему ограничены размером 2 ГБ в CLR 4.0?

Поскольку коллекции, такие как List<T>, используют массив для хранения элементов, это означает, что приложение .NET, работающее на 32-битной основе, сможет удерживать в два раза больше элементов ссылочного типа в списке по сравнению с тем же приложением, работающим на 64-битном , Это довольно удивительно.

Кто-нибудь знает, исправлено ли это ограничение в CLR 4.0 (на данный момент у меня нет установленной версии 4.0).

+6

Update 2012: На .NET 4.5, на 64-разрядных системах, разработчики теперь могут выделять объекты больше (гораздо больше), чем 2 Гб. Предел 2 ГБ мертв. http://www.centerspace.net/blog/nmath/large-matrices-and-vectors/?preview=true&preview_id=221&preview_nonce=7d1678c20c – Paul

+2

Исправлена ​​ссылка http://www.centerspace.net/blog/nmath/ large-matrices-and-vectors/ –

+1

Даже исправленные ссылки мертвы :( – RBT

ответ

50

Это хуже, чем вы - пространство процесса, когда вы работаете в .NET на 32-битной основе, намного меньше теоретического предела. В 32-битных .NET-приложениях мой опыт в том, что вы всегда будете получать ошибки в памяти где-то около 1,2-1,4 гб использования памяти (некоторые говорят, что могут получить до 1,6 ... но я никогда не видел этого). Конечно, это не проблема для 64-битных систем.

Это, как говорится, один массив опорных типов 2 ГБ, даже на 64-битных системах, представляет собой огромное количество объектов. Даже с 8-байтовыми ссылками у вас есть возможность выделить массив из 268 435 456 ссылок на объекты - каждый из которых может быть очень большим (до 2 ГБ, больше, если они используют вложенные объекты). Это больше памяти, чем когда-либо действительно требовалось большинством приложений.

Один из членов CLR team blogged about this с некоторыми вариантами способов обойти эти ограничения. В 64-битной системе делать что-то вроде своего BigArray <T> было бы жизнеспособным решением для размещения любого количества объектов в массиве - гораздо больше, чем ограничение на один объект 2gb. P/Invoke может также выделять большие массивы.


Edit: Я говорил об этом, а также - я не считаю, что это поведение изменилось для .NET 4. Поведение остается неизменным с самого начала .NET.


Edit: .NET 4.5 теперь будут иметь возможность в 64 явно разрешить объекты, чтобы быть больше, чем 2gb, установив gcAllowVeryLargeObjects в app.config.

+0

Я знаю все ограничения на 32 бит, но на самом деле это не вопрос моего вопроса. Неожиданным было то, что на 64-бите ситуация на самом деле хуже. Я посмотрю сообщение в блоге. Спасибо за ссылку. –

+0

Нет проблем - я просто добавил, что это действительно не хуже, чем 64 бит, чем 32 бит. Теоретический предел составляет 1/2 объекта, но поскольку вы действительно ограничены общим объемом 1,4 Гбайт пространства, нет никакого способа сделать массив ссылок на объекты даже близко к половине допустимого размера. (Каждая ссылка требует, чтобы она указывала на что-то, а также на размер ссылки .... так что вы действительно набираете большую часть времени вокруг ссылок на 1/4gb в .NET 32bit). –

+0

В ответ на Edit: Я подозреваю, что вы правы. Насколько я могу судить, ограничение всегда было там, и я не смог найти ничего, указав, что предел был изменен. Я могу понять, почему MS может не захотеть обратиться, но действительно странно, что переход на 64-разрядный уровень фактически приведет к меньшему «пространству» для отдельных коллекций. –

13

Это большое дело в числовом поле. Любой, кто использует библиотеки числовых классов в .NET, имеет свои матрицы, хранящиеся под массивами. Это можно сделать так, чтобы встроенные библиотеки могли вызывать число-хруст. Ограничение 2 ГБ серьезно затрудняет размер матриц, доступных в 64-разрядной версии .NET. Подробнее here.

+1

Мы поговорили с Microsoft об этой проблеме. Скорее всего, он будет исправлен в .NET 4.0, но они были очень восприимчивы к поиску решения. Я думаю, что в итоге мы получим массивы с длинными индексами, но, скорее, какой-то гигантский объект blob. –

+0

Как производительность массива 65536 * 65536 поплавка сравнивается с массивом 65536 65536 поплавков? Производительность 256 массивов из 256 поплавков будет ниже, чем у массива 256 * 256, так как последняя будет иметь лучшую локальность кэша, а первая не будет, но если кто-то обращается к строкам матрицы, которые достаточно локализованы для выгоды от локализации кэша, я бы подумал, что процессор сможет кэшировать ссылки на объекты-таблицы. – supercat

15

.NET Framework 4.5 позволяет создавать массивы размером более 2 ГБ на 64-битных платформах. Эта функция не включена по умолчанию, ее нужно активировать через конфигурационный файл, используя элемент gcAllowVeryLargeObjects.

http://msdn.microsoft.com/en-us/library/hh285054(v=vs.110).aspx

+0

Я не заметил. Спасибо за ссылку. –

+0

Еще только 4 ГБ !? почему они не могут сделать настоящие 64-битные? –

+0

@ Запишите, где вы видите 4 ГБ? –