Pregunta

Tengo una aplicación de consola que permite a los usuarios especificar variables para procesar. Estas variables vienen en tres sabores: cadena, doble y largo (con el doble y el doble, los tipos más utilizados). El usuario puede especificar las variables que le gusten y en cualquier orden para que mi sistema tenga que poder manejar eso. Para este fin en mi aplicación, los había estado almacenando como objeto y luego lanzarlos/desactivarlos según sea necesario. por ejemplo:

public class UnitResponse
{
    public object Value { get; set; }
}

Entiendo que los objetos en caja toman un poco más de memoria (aproximadamente 12 bytes) que un tipo de valor estándar.

Mi pregunta es: ¿sería más eficiente usar la palabra clave dinámica para almacenar estos valores? Podría superar el problema del boxeo/desempaquetado, y si es más eficiente, ¿cómo impactaría esto el rendimiento?

EDITAR

Para proporcionar un contexto y evitar el "¿Está seguro de que está utilizando suficiente RAM para preocuparse por esto" en mi peor de los casos, tengo 420,000,000 de puntos de datos de los que preocuparse (60 variables * 7,000,000 de registros). Esto se suma a un montón de otros datos que guardo sobre cada variable (incluidos algunos booleanos, etc.). Por lo tanto, reducir la memoria tiene un gran impacto.

¿Fue útil?

Solución

Ok, entonces el real La pregunta aquí es "Tengo un enorme conjunto de datos que estoy almacenando en la memoria, ¿cómo optimizo su rendimiento tanto en el espacio de tiempo como en la memoria?"

Varios pensamientos:

  • Tienes toda la razón al odiar y temer el boxeo. El boxeo tiene grandes costos. Primero, sí, los objetos en caja toman memoria adicional. En segundo lugar, los objetos en caja se almacenan en el montón, no en la pila o en los registros. Tercero, son basura recolectada; Cada uno de esos objetos debe ser interrogado en la hora de GC para ver si contiene una referencia a otro objeto, que nunca lo hará, y eso es mucho tiempo en el hilo de GC. Es casi seguro que necesitas hacer algo para evitar el boxeo.

Dinámica no es; Es el boxeo más una gran cantidad de otros gastos generales. (La dinámica de C#es muy rápida en comparación con otros sistemas de despacho dinámico, pero no es rápido ni pequeño en términos absolutos).

Es asqueroso, pero podría considerar usar una estructura cuyo diseño comparte la memoria entre los diversos campos, como un sindicato en C. hacerlo es Realmente realmente asqueroso y para nada seguro Pero puede ayudar en situaciones como estas. Haga una búsqueda web de "structLayoutAttribute"; Encontrarás tutoriales.

  • Largo, doble o cadena, ¿en serio? ¿No se puede ser int, flotación o cadena? ¿Los datos realmente superan a varios miles de millones en magnitud o precisos a 15 decimales? ¿No INT y Float no harían el trabajo para el 99% de los casos? Son la mitad del tamaño.

Normalmente no recomiendo usar Float sobre el doble porque es una economía falsa; Las personas a menudo economizan de esta manera cuando tienen un número, como los ahorros de cuatro bytes van a marcar la diferencia. La diferencia entre 42 millones de flotadores y 42 millones de dobles es considerable.

  • ¿Hay regularidad en los datos que puede explotar? Por ejemplo, suponga que de sus 42 millones de registros, solo hay 100000 valores reales para, por ejemplo, cada largo, 100000 valores para cada doble y 100000 valores para cada cadena. En ese caso, usted hace un almacenamiento indexado de algún tipo para los largos, dobles y cadenas, y luego cada registro obtiene un entero donde los bits bajos son el índice, y los dos bits superiores indican de qué almacenamiento sacarlo. Ahora tiene 42 millones de registros cada uno que contiene un INT, y los valores se almacenan en una forma muy bien compacta en otro lugar.

  • Almacene los booleanos como bits en un byte; Escribe propiedades para hacer el cambio de broca para sacarlas. Ahórrese varios bytes de esa manera.

  • Recuerde que la memoria es en realidad espacio en disco; Ram es solo un caché conveniente encima. Si el conjunto de datos será demasiado grande para mantener en RAM, entonces alguna cosa Volverá al disco y lo volverá a leer más tarde; Ese podría ser usted o podría ser el sistema operativo. Es posible que sepa más sobre su localidad de datos que el sistema operativo. Puede escribir sus datos en el disco en una forma convenientemente amable (como un árbol B) y ser más eficiente para mantener las cosas en el disco y solo llevarlo a la memoria cuando lo necesite.

Otros consejos

Creo que podrías estar mirando lo incorrecto aquí. Recuerda lo que hace Dynamic. Eso inicia el compilador nuevamente, en proceso, en tiempo de ejecución. Carga cientos de miles de bytes de código para el compilador, y luego en cada sitio de llamadas emite cachés que contienen los resultados de la IL recién emitida para cada operación dinámica. Estás gastando unos cientos de miles de bytes para ahorrar ocho. Eso parece una mala idea.

Y, por supuesto, no guardas nada. "Dynamic" es solo "objeto" con un sombrero elegante. Los objetos "dinámicos" todavía están en caja.

No. dynamic tiene que ver con Cómo se realizan las operaciones en el objeto, no cómo se almacena el objeto en sí. En este contexto particular, los tipos de valor aún estarían en caja.

Además, ¿todo este esfuerzo realmente vale 12 bytes por objeto? ¿Seguramente hay un mejor uso para su tiempo que ahorrar unos pocos kilobytes (si eso) de RAM? ¿Ha demostrado que el uso de RAM por su programa es en realidad un problema?

No. Dynamic simplemente lo almacenará como un objeto.

Lo más probable es que se trata de una micro optimización que proporcionará poco o ningún beneficio. Si esto realmente se convierte en un problema, entonces hay otros mecanismos que puede usar (genéricos) para acelerar las cosas.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top