2010-09-24 12 views
9

Es cierto que las colecciones genéricas funcionan mejor que las colecciones no genéricas para los tipos de valores. (es decir, List vs. ArrayList).Dónde se almacenan los tipos de valores en (C#) Colecciones genéricas

¿Pero por qué es eso, aparte del paso de boxeo-unboxing? ¿Dónde se almacenan los objetos de tipo de valor una vez agregados a la colección? En colecciones no genéricas, se guardarán en cajas y se almacenarán en montón, ¿qué hay de diferente en genéricos?

+0

Para el mismo número de enteros, sizeof (Lista ) ~ = sizeof (int []) ~ = 1/2 sizeof (ArrayList en x86) ~ = 1/3 sizeof (ArrayList en x86-64). Además, la ubicación de los datos apesta a ArrayList debido al boxeo y produce una fragmentación de memoria superior a la necesaria. –

Respuesta

1

Una ArrayList es una matriz local de referencias a objetos almacenados en el montón.

Una lista genérica de tipos de referencias es una matriz local de referencias a objetos almacenados en el montón.

Una lista genérica de tipos de valores es una matriz local de esos tipos de valores.

Hay dos áreas de memoria, que la mayoría de las referencias llaman "The Stack" y "The Heap". La mayoría de las personas que usan esos términos no tienen idea de por qué. ("The Stack" puede ser una pila, pero The Heap casi con certeza no es un montón). Prefiero los términos "Por aquí" y "Por allá". Cuando está encuadrado, los datos del tipo de valor se almacenan "Por Encima". Cuando se almacena en una matriz (tal vez dentro de una lista genérica), los datos de tipo de valor se almacenan "Por aquí". "Por aquí" es mejor.

+0

"Por aquí" - "por allá" ??? ¿¿¿¿Qué???? ¿Y qué es un "arreglo local"? Esta respuesta es más confusa que nada. –

+0

@ 0xA3: una matriz local es una que se almacena en "La pila". ¿Es más esclarecedor así redactado? –

+2

Bien, entonces tu afirmación no es correcta (si te refieres a apilar en el sentido común).Tanto 'ArrayList' como' List 'usan un System.Array como almacenamiento interno que es un tipo de referencia y se almacena" por allí ". –

11

En genéricos, como List<T>, todavía se almacenan en el montón. La diferencia es que, internamente, un List<int> forma una única matriz de enteros y puede almacenar los números directamente. Con ArrayList, termina almacenando una matriz de referencias a valores enteros encuadrados.

0

Las ganancias de rendimiento en genéricos son generalmente solo con respecto a los tipos de valores utilizados con genéricos en comparación con los tipos de valores almacenados en equivalentes no genéricos.

Esto se debe a que con los tipos de valores genéricos no es necesario convertir a objeto y se almacenan en el montón (en recuadro). De hecho, pueden permanecer en la pila que es más eficiente.

http://msdn.microsoft.com/en-us/library/ms172181.aspx

8

El detalle de implementación relevante es que el almacenamiento subyacente para un List<T> es un T []. Por lo tanto, para un List<int>, los valores se almacenarán en un int []. Los enteros se almacenan en un trozo contiguo de memoria, asignado desde el montón recogido de basura.

Lo que lo hace tan rápido no es solo que los enteros no estén encasillados, sino que un int [] funciona muy bien con la memoria caché de la CPU. Cuando lee el primer elemento, esencialmente obtiene los siguientes 15 gratis sin tener que leer la RAM lenta o la memoria caché secundaria. Esto no funciona tan bien para un int encuadrado porque es tan grande y la referencia extra puede tener una localidad de caché pobre. Sin embargo, el recolector de basura realmente ayuda a reducir el costo compactando el montón.

+0

Ah, la única respuesta que dice explícitamente que 'List ' de hecho utiliza una matriz como una tienda de respaldo (y también está bien). Una 'List ' es simplemente un contenedor para una matriz que agrega soporte para cambiar el tamaño, y de hecho, casi todos los tipos de recolección se reducen a las matrices, excepto para colecciones especiales como 'LinkedList '. –

+0

Entonces un 'ArrayList' tiene un doble golpe de rendimiento. En primer lugar, debe desreferenciar el valor de la matriz para obtener el objeto (tipo de valor encuadrado), y luego debe desempaquetarlo. –

+0

Pero si el almacén de respaldo para 'ArrayList' es' object [] ', entonces primero debe buscar el elemento en la matriz, que le da una referencia al objeto que contiene el int. Tienes que desreferenciar eso para obtener el objeto, luego debes desempaquetarlo. Compare eso con 'List', donde todo lo que tiene que hacer es tomar el artículo del almacén de respaldo' int [] '. –

Cuestiones relacionadas