2011-05-05 14 views
10

Tenemos una aplicación que contiene un gran número de objetos en varios Dictionary s, algunos de los cuales crecen continuamente durante la vida útil de la aplicación (aplicación comercial con muchos instrumentos y órdenes/intercambios en continuo crecimiento).Large Object Heap friendly IDictionary

Estamos teniendo problemas con OutOfMemoryException debido a la fragmentación del montón de objetos grandes.

Para contrarrestar esto, he tratado de escribir un diccionario 'grande' que se implementa como un diccionario de dos niveles donde todos los diccionarios de hoja no son lo suficientemente grandes para ser asignados en el LOH. He usado un algoritmo de hash consistente para evitar tener que repetir todo el diccionario cuando un solo segmento se vuelve demasiado grande. El 'círculo' hash consistente es TreeDictionary de la biblioteca de colecciones C5.

Mi pregunta es, ¿hay mejores estructuras de datos (o quizás mejores implementaciones de la que describí) para C#?

actualización

Ésta es la aplicación para el diccionario 'grande': https://gist.github.com/956621

entiendo que no es infalible, ya que ni el umbral LOH montón es en la especificación, ni el tamaño de cada entrada de diccionario o algoritmo de escala. Sin embargo, esto es actualmente lo mejor que puedo pensar para evitar que la aplicación explote a mediodía.

+1

Podría ayudar saber qué problemas ve con su implementación actual? –

+0

Si está utilizando su diccionario como almacén de valores-clave para objetos planos, puede considerar un archivo mapeado en memoria. – hsmiths

+0

¿Ha verificado que no está "goteando" memoria en ningún lugar (como en las referencias retenidas 'pérdidas' de memoria) –

Respuesta

1

Creo que esto requiere un cambio de algoritmo.

Según lo que escuché y entendí, GC es bastante bueno para empacar y desfragmentar la memoria. Entonces, su problema surge del simple hecho de que usted guarda demasiados datos en la memoria.

¿Cuántos datos conserva en la memoria?

¿Pensó en usar la base de datos? uno compacto podría ser suficiente.

O simplemente dile a tu cliente que para ejecutar correctamente tu aplicación, necesita 16 GB de memoria. Y si su aplicación necesita todos esos 16 GB de memoria, definitivamente hay algo mal.

Editar: En cuanto a su problema de un lado diferente y después de leer su edición que consiguió la pregunta: ¿De qué tamaño son los objetos? ¿O contienen listas largas o matrices? ¿Con qué frecuencia quita/agrega esos objetos?

Creo que el problema puede no estar en el diccionario en sí, pero los objetos son demasiado grandes y se eliminan/agregan con demasiada frecuencia. Tal vez usar algún tipo de captura o grupo podría ser rentable. Y si usa listas, entonces cree esas listas con prealocated.

Y tal vez el uso de estructuras imutables en lugar de clases mutables puede facilitar la fragmentación.

+0

+1 "¿Cuántos datos conserva en la memoria?" En lugar de modificar tu diccionario, vuelve a evaluar tu requerimiento con tu experiencia adquirida recientemente. –

+0

El objetivo a largo plazo es reducir el número de transacciones/pedidos que tenemos en la memoria, pero no es factible a corto plazo. Desafortunadamente, ninguno está reemplazando todas las máquinas XP de 32 bits del operador con un sistema operativo de 64 bits. – SimonC

+0

+1 base de datos local es la única mejor opción –

3

Un diccionario es una estructura de datos desafortunada cuando es la más grande en su aplicación. La tabla hash suele duplicarse cuando se llena demasiado y requiere una sobreasignación del 150% durante el cambio de tamaño, justo en el momento crítico. La tabla hash funciona bastante bien cuando es gigantesca pero requiere una asignación consecutiva que enfatiza los algoritmos de montón.

Puede disminuir estas desventajas con tablas hash multinivel, por ejemplo, utilizando un byte del hashcode como un índice en 256 hashtables.Esto agrega un poco de sobrecarga, pero lo más importante es que esta y otras estrategias están llenas de peligros al jugar con la aleatoriedad, como la de los códigos hash que se obtienen y, potencialmente, hacer las cosas mucho, mucho peor en cuanto a rendimiento. El uso de este enfoque requiere una buena base teórica y pruebas empíricas sólidas. Pero puede funcionar

Otra estrategia es preasignar la estructura de datos más grande para el peor de los casos y asignarla con anticipación. No es necesaria una asignación detallada, pero ahora enfrenta el fantasma de una falla catastrófica si alguna vez se le acaba. Es una opción.

+0

Creo que el algoritmo de hashing de varios niveles que tengo está bien en cuanto a rendimiento. Estamos preasignando matrices donde sea posible, pero no siempre es factible/deseable asignar una matriz directamente para el peor de los casos. – SimonC

+0

¿Ayudaría preasignar las tablas especificando la capacidad en el constructor del diccionario? – hsmiths

+0

@shmith: si sabe que probablemente habrá un millón de entradas, es útil decirlo de inmediato. Pero entonces el verdadero dolor comienza cuando llegas a un millón y uno. –