2011-12-27 9 views
10

excepción de tipo System.OutOfMemoryException fue arrojado al intentar añadir 23997908th elemento en un HashSet<Int32>.OutOfMemoryException al agregar más elementos a una muy grande HashSet <Int32>

Necesitamos mantener una colección única de alto rendimiento de tamaño entero de Int32 .MaxValue es decir 2147483647. HashSet de Int32 puede almacenar solo 23997907 artículos en él. Buscando una sugerencia para resolver este problema.

+3

Sólo por pura curiosidad: ¿para qué necesitas esto? –

+1

http://blog.mischel.com/2008/04/09/hashset-limitations/ –

+0

@MikeNakis: como se menciona en la publicación, necesitamos mantener una colección única de alto rendimiento de número entero para satisfacer algunos de nuestros requisitos – Debasis

Respuesta

14

capacidad de un objeto HashSet (Of T) es la cantidad de elementos que el objeto puede contener. La capacidad del objeto aumenta automáticamente a medida que se le agregan elementos.

si está usando el sistema de 64 bits, puede aumentar la capacidad máxima de hasta 2 mil millones de hashset elementos estableciendo el atributo enabled de los gcAllowVeryLargeObjects de cierto en el entorno de ejecución.

puede habilitar esta configuración del archivo de configuración,

<configuration> 
<runtime> 
    <gcAllowVeryLargeObjects enabled="true" /> 
    </runtime> 
</configuration> 

Comprobar este enlace MSDN para establecer la configuración.

Actualización:

Por encima de config gcAllowVeryLargeObjects apoya sobre el marco .Net 4.5 solamente.

+2

Framework 4.5 en adelante solamente ... –

+1

De repente estoy mucho más entusiasmado con .NET 4.5. Me he topado con el límite de 2 GB demasiadas veces. –

+0

@MitchWheat: sí, me olvidé de mencionarlo. actualizando mi respuesta. Gracias – mehul9595

9

HashSet grows by doubling. Entonces, cuando tiene 23.997.907 elementos en la lista e intenta agregar el siguiente, intenta duplicar el tamaño de su matriz de respaldo. Y esa asignación hace que exceda la memoria disponible. Supongo que está ejecutando esto en un sistema de 32 bits, porque en un sistema de 64 bits, un HashSet<object> puede contener más de 89 millones de elementos. El límite es de aproximadamente 61.7 millones de elementos en el tiempo de ejecución de 32 bits.

Lo que debe hacer es asignar previamente HashSet para contener tantos elementos como necesite. Lamentablemente, no hay directa manera de hacerlo. HashSet no tiene un constructor que lo preasigne con una capacidad determinada.

Puede, sin embargo, crear un List, lo utilizan para inicializar el HashSet, y luego llamar a Clear en el HashSet. Eso termina dándole un HashSet que no tiene elementos, pero una capacidad máxima que usted solicitó. Mostré cómo hacer eso en una publicación de blog: More on .NET Collection Sizes.

Los límites en el tamaño HashSet se deben al límite de dos gigabytes en .NET. Ningún objeto puede ser más grande que dos gigabytes. El número es en realidad un poco más pequeño, debido a gastos generales de asignación.

+0

Dot net está permitiendo solo 134,217,728 elementos para agregar en una lista de Int32 – Debasis

+0

@Debasis: si está ejecutando en modo de 64 bits, esperaría a 'List ' para darle más de 500 millones de entradas. Sus 134 millones de elementos funcionan en más de 512 megabytes de memoria, lo que fácilmente podría ser más de lo que puede asignar en el tiempo de ejecución de 32 bits. 134 millones es bastante similar al "HashSet" más grande que puedes construir, incluso en el modo de 64 bits. –

0

En este punto, creo que necesitaría usar una base de datos para conservar sus elementos (o sus claves hash) ya que son demasiados elementos para almacenar en los objetos .NET predeterminados. También podría escribir un objeto personalizado que tenga las mismas propiedades que HashSet, pero podría ser más problemático que usar una tabla de base de datos para almacenar los valores hash.

1

Para solucionar este problema, creé una clase que implementa los métodos y propiedades de HashSet (contiene, agrega, cuenta, ...) y detrás de las escenas mantiene una matriz de HashSets para almacenar los datos reales. La primera implementación simplemente llegó al máximo de cada HashSet uno a uno y se movió al siguiente en la matriz cuando estaba lleno. La última toma un mod de la clave hash como el índice de la matriz HashSet interna. Esto funciona bien para mí, ya que las claves son bastante aleatorias, por lo que la distribución de valores a la matriz HashSets es bastante pareja.

Cuestiones relacionadas