2009-03-10 14 views
9

¿Cuál es la sobrecarga de generar una gran cantidad de objetos temporales (es decir, para resultados provisionales) que "mueren jóvenes" (nunca promovidos a la próxima generación durante un intervalo de recolección de basura)? Asumo que la "nueva" operación es muy barata, ya que es solo un incremento de puntero. Sin embargo, ¿cuáles son los costos ocultos de tratar con esta "camada" temporal?Objetos de vida corta

+0

Si realmente tiene objetos simples, y especialmente si son fáciles de restablecer, cree un grupo de objetos y vuelva a utilizarlos. Esto también puede funcionar para objetos complicados. Una vez tuve una aplicación que creaba miles de pequeños mapas de bits para dibujar texto interem que no se podía dibujar directamente en una página por razones lógicas. Por 1000s de pgs, los tamaños fueron reutilizados. En lugar de 'disponer', los almacené en una tabla hash 'libre' con la clave WidthxHeight (señalando una lista de mapas de bits) y la revisé antes de hacer NEW. Si está allí, quítelo, póngalo en uso. Suena caro, pero hacer bitmaps debe ser peor. Enorme aceleración. – FastAl

+0

@FastAl Supongo que quiere decir algo como ['System.Drawing.Bitmap'] (https://msdn.microsoft.com/en-us/library/system.drawing.bitmap%28v=vs.110%29.aspx) que "encapsula un mapa de bits GDI +" que implica [algo así como una syscal para crear/destruir] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms724291%28v=vs.85%29. aspx) ellos. Eso es bastante diferente de los objetos .net puros, que supongo que el OP está preguntando. – binki

+0

@binki - Tiene razón sobre el mapa de bits, es mucho más costoso que los objetos simples. Pero si el lazo es lo suficientemente fuerte y no hace mucho con los objetos ... aún podría valer la pena reutilizarlos. GC todavía tiene que hacer algo eventualmente. Por supuesto, en ese caso, depende. No menciona el tamaño, los mapas de bits pueden ser temporales y, como mencionas, hay un costo oculto para ellos. Los objetos nuevos, si son grandes, podrían borrarse antes de su uso, si su código sobrescribe lo que hay, de todos modos podría significar una aceleración de 2x (eso es algo así como ninja). – FastAl

Respuesta

12

No mucho - el recolector de basura es muy rápido para gen0. También se sintoniza, ajustando el tamaño de gen0 dependiendo de cuánto se las arregla para recolectar cada vez que va. (Si se logra recolectar mucho, reducirá el tamaño de gen0 para recogerlo la próxima vez, y viceversa).

La última prueba es cómo su aplicación funciona bien. Perfmon es muy útil aquí, muestra cuánto tiempo se ha gastado en GC, cuántas colecciones ha habido de cada generación, etc.

+1

Downvoters: los comentarios son bienvenidos, de lo contrario, nadie (incluido yo) sabrá con qué está en desacuerdo con mi respuesta ... –

+1

¿Dónde obtengo PerfMon? – Karl

+2

Está casi seguro instalado en su caja de Windows. Pulse Windows-R y simplemente escriba "perfmon". De lo contrario, encontrarlo dependerá de la versión de Windows que esté utilizando. –

3

Como dices, la asignación en sí es muy económica. El costo de generar muchos objetos efímeros es una recolección de basura más frecuente, ya que se activa cuando se agota el presupuesto de la generación 0. Sin embargo, una colección de generación 0 es bastante barata, por lo que siempre que su objeto sea de corta duración, lo más probable es que la sobrecarga no sea significativa.

Por otro lado, el ejemplo común de concatenar muchas cadenas en un bucle empuja al recolector de basura significativamente, por lo que todo depende de la cantidad de objetos que cree. No hace daño pensar en la asignación.

El costo de la recolección de basura es que los hilos administrados se suspenden durante la compactación.

1

En general, esto no es algo de lo que deba preocuparse y parece que comienza a estar muy cerca de la "micro-optimización". El GC fue diseñado con la suposición de que una "aplicación bien ajustada" tendrá todas sus asignaciones en Gen0, lo que significa que todos "mueren jóvenes". Cada vez que asigna un nuevo objeto, siempre está en Gen0. No se realizará una recopilación hasta que se pase el umbral Gen0 y no haya suficiente espacio disponible en Gen0 para mantener la siguiente asignación.

La "nueva" operación es en realidad un montón de cosas:

  1. asignar memoria
  2. ejecutar el tipo constructor
  3. devolver un puntero a la memoria
  4. incrementar el puntero siguiente objeto
0

Si estos objetos nunca se promocionan desde la Generación 0, verá un rendimiento bastante bueno. El único costo oculto que puedo ver es que si supera el presupuesto de su Generación 0, forzará que el GC compacte el montón, pero el GC se autoajustará, por lo que no es una gran preocupación.

0

La recolección de basura es generacional en .Net. Los objetos de vida corta se recolectarán primero y con frecuencia. La colección Gen 0 es barata, pero dependiendo de la escala de la cantidad de objetos que esté creando, podría ser bastante costosa. Diría un generador de perfiles para ver si está afectando el rendimiento. Si es así, considere cambiarlos a estructuras. Estos no necesitan ser recolectados.

1

Aunque la nueva operación está diseñada y escrita de manera eficiente, no es gratuita y lleva tiempo asignar nueva memoria. La biblioteca de asignación de memoria necesita rastrear qué fragmentos están disponibles para la asignación y la memoria recién asignada se pone a cero.

Crear muchos objetos que mueren jóvenes también desencadenará la recolección de basura más a menudo y esa operación puede ser costosa. Especialmente con los recolectores de basura "stop the world".

He aquí un artículo de MSDN sobre cómo funciona: http://msdn.microsoft.com/en-us/magazine/bb985011.aspx

Nota: que describe cómo llamar a la recolección de basura es caro, ya que necesita para construir el gráfico de objetos antes de que pueda comenzar la recolección de basura.

+0

Del artículo vinculado: "Estas pruebas también muestran que se necesita menos de 1 milisegundo en un Pentium de 200Mhz para realizar un GC completo de la generación 0. El objetivo de Microsoft es hacer que los GC no ocupen más tiempo que un error de página ordinario". IMO "muy caro". No es gratis, sin duda, pero si (cont.) –

+0

el código es más legible con muchos objetos pequeños y efímeros, prefiero seguir haciéndolo hasta que se pruebe que es un cuello de botella que doblar mi diseño. fuera de forma para contrarrestar un "problema" de rendimiento que puede no ser un problema en absoluto. –

+0

Estoy de acuerdo y no estoy diciendo que deberían cambiar la forma en que escriben los programas. La pregunta fue cuáles son los gastos generales subyacentes e intenté dar una respuesta. –

Cuestiones relacionadas