2010-07-09 47 views
13

La mayoría de los idiomas modernos han incorporado la recolección de basura (GC). p.ej. Java, lenguajes .NET, Ruby, etc. De hecho, GC simplifica el desarrollo de aplicaciones de muchas maneras.¿Cuáles son las desventajas al usar Garbage Collection?

Estoy interesado en conocer las limitaciones/desventajas de escribir aplicaciones en los idiomas GCed. Asumiendo que la implementación de GC es óptima, me pregunto si GC nos puede limitar para tomar algunas decisiones de optimización.

+2

http://stackoverflow.com/questions/1424660/garbage-collection-vs-non-garbage-collection-programming-languages ​​ –

+0

@tusbar Aunque esa pregunta tiene un título genérico, solo pregunta sobre los errores que los desarrolladores cometerían si están programando en lenguajes sin GC. – rpattabi

Respuesta

21

Las principales desventajas de utilizar un recolector de basura, en mi opinión, son los siguientes:

  1. limpieza no determinista de los recursos. A veces, es útil decir "He terminado con esto, y quiero que se limpie AHORA". Con un GC, esto generalmente significa obligar al GC a limpiar todo, o simplemente esperar hasta que esté listo; ambos le quitan algo de control como desarrollador.

  2. Posibles problemas de rendimiento que surgen del funcionamiento no determinista del GC. Cuando se recolecta el GC, es común ver bloqueos (pequeños), etc. Esto puede ser particularmente problemático para cosas como simulaciones en tiempo real o juegos.

+16

+1 * Agrega GC a la lista de razones por las que muere en los juegos * – corsiKa

+0

@glowcoder: ¿No es genial? Me encanta poder tener algo que culpar por eso ...;) –

+0

¿La limpieza no determinista es un problema común de GC? o específico para implementaciones particulares de GC? – rpattabi

2

Si tiene confianza (buena) en sus habilidades de administración de memoria, no hay ninguna ventaja.

El concepto se introdujo para minimizar el tiempo de desarrollo y debido a la falta de expertos en programación que entendieron a fondo la memoria.

+11

"confidente" es diferente de "bueno";) –

+3

Hay muchas ventajas para un GC, incluso si usted es muy hábil y confía en su gestión de memoria. Esto es especialmente cierto si está usando un GC compactador ... –

+0

@Sean, gracias: D –

6

Para .NET, hay dos desventajas que puedo ver.

1) Las personas asumen que el GC lo sabe mejor, pero no siempre es así. Si realiza ciertos tipos de asignaciones, puede provocar algunas muertes realmente desagradables sin invocación directa del GC.

2) Los objetos de más de 85k van a LOH, o a Large Object Heap. Ese montón actualmente NUNCA está compactado, por lo que, de nuevo, su programa puede experimentar excepciones de memoria insuficiente cuando realmente el LOH no está compactado lo suficiente como para que realice otra asignación.

Ambos de estos errores se muestran en código que he publicado en esta pregunta:

How do I get .NET to garbage collect aggressively?

+0

Large Object Heap es interesante. ¿Es algo específico de .NET? – rpattabi

+1

@ ragu.pattabi: Sí. Básicamente, en .NET, cualquier asignación única de 85k (es decir, una gran variedad de estructuras) se asignará utilizando una asignación de estilo "tradicional" y no se compactará con el resto del montón de GC. –

+0

@Reed Copsey: Eso es interesante. Veo, observar las implementaciones específicas de GC podría apuntar a limitaciones específicas para ellos, aunque la mayoría de las limitaciones son comunes. – rpattabi

1

El mayor problema cuando se trata de rendimiento (especialmente en o sistemas de tiempo real) es, que su programa puede experimentar algunas demoras inesperadas cuando la GC entra en acción. Sin embargo, la GC moderna trata de evitar esto y puede ajustarse para propósitos de tiempo real.

Otra cosa obvia es que usted mismo no puede administrar su memoria (por ejemplo, asignar a la memoria local numa), lo que puede necesitar hacer cuando implemente software de bajo nivel.

+0

Normalmente, si tiene requisitos de nivel muy bajo (es decir: memoria local numa), puede recurrir a la asignación tradicional para eso ... –

+0

Al contrario de lo que pensaba, .NET tiene un sabor para aplicaciones integradas denominado .NET Micro Framework. Tiene GC. – rpattabi

+0

@Reed Copsey: Pero luego tienes IMO ya un sistema híbrido que permite ambos. Creo que la mayoría de los lenguajes de GC no permiten tal cosa. –

11

Tómelo de un programador de C ... se trata de costo/beneficio y el uso apropiado

Los algoritmos de recolección de basura, tales como tricolor/marcar y barrido existe latencia entre una frecuencia significativa el recurso se 'pierde' y se libera el recurso físico. En algunos momentos, el GC pausará la ejecución del programa para realizar la recolección de basura.

Siendo un programador C mucho tiempo, te puedo decir:

a) Manual) la recolección de basura libre (es difícil - Esto se debe a que por lo general hay una mayor tasa de error en la colocación humana del libre () llamadas que algoritmos GC.

b) Manual() la recolección de basura cuesta tiempo - ¿El tiempo dedicado a la eliminación de errores supera las pausas de un milisegundo de un GC? Puede ser beneficioso utilizar la recolección de basura si está escribiendo un juego que decir un kernel incrustado.

Pero, cuando no puede permitirse la desventaja en tiempo de ejecución (recursos correctos, restricciones en tiempo real), entonces realizar una asignación de recursos manual es probablemente mejor. Puede llevar tiempo, pero puede ser 100% eficiente.

¿Intenta imaginar un kernel de sistema operativo escrito en Java? o en el tiempo de ejecución de .NET con GC ... Solo observe cuánta memoria acumula la JVM cuando ejecuta programas simples. Soy consciente de que los proyectos existen así ... me hacen sentir un poco enfermo.

Solo tenga en cuenta que mi linux box hace las mismas cosas hoy en día con 3GB de RAM que cuando tenía 512MB de RAM hace años. La única diferencia es que tengo mono/jvm/firefox, etc. ejecutándose. El caso comercial para GC es claro, pero todavía me hace sentir incómodo muchas veces.

Los buenos libros:

Dragon book (recent edition), Modern Compiler Implementation in C

+0

+1, precisamente. –

+1

Estoy de acuerdo con esto, pero ... "realizar la asignación manual de recursos" de una manera que es "100% eficiente" a menudo lleva a escribir básicamente su propio "mini-GC". Es MUCHO esfuerzo hacerlo bien y, a menudo, lleva a otros problemas. (Por ejemplo, tratar de evitar la fragmentación de la memoria es muy desafiante en C ...) –

+0

@Aiden Bell: No estoy seguro si esto es radical. Pero ¿por qué no cuando la memoria no es un problema en un futuro cercano? La mejora del núcleo del sistema operativo con GC podría beneficiar a todas las aplicaciones que se ejecutan en el sistema operativo, donde las mejoras en las aplicaciones solo pueden ayudarlas individualmente. GC podría aprender sobre las aplicaciones que ejecuta (¿AI?) Y comportarse de una manera óptima. – rpattabi

1

Es casi imposible hacer un trabajo de administrador de memoria no-GC en un entorno multi-CPU sin necesidad de una cerradura para ser adquirida y liberado cada vez que la memoria es asignado o liberado. Cada adquisición o liberación de bloqueo requerirá una CPU para coordinar sus acciones con otras CPU, y dicha coordinación tiende a ser bastante costosa. Un sistema basado en recolección de basura puede permitir que ocurran muchas asignaciones de memoria sin requerir bloqueos u otra coordinación entre CPU. Esta es una gran ventaja. La desventaja es que muchos pasos en la recolección de basura requieren que la CPU coordine sus acciones, y obtener un buen rendimiento generalmente requiere que tales pasos se consoliden en un grado significativo (no hay mucho beneficio para eliminar el requisito de coordinación de la CPU en cada asignación de memoria si Las CPU deben coordinarse antes de cada paso de la recolección de basura). Dicha consolidación a menudo hará que todas las tareas en el sistema se pausen durante períodos de tiempo variables durante la recopilación; en general, cuanto más largas son las pausas que uno está dispuesto a aceptar, menos tiempo total se necesitará para la recolección.

Si los procesadores regresaran a un sistema de manejador/apuntador basado en descriptor (similar al que usaba el 80286, aunque hoy en día ya no se usarían segmentos de 16 bits), sería posible realizar la recolección de basura al mismo tiempo que otras operaciones (si se utilizaba un identificador cuando el CG quería moverlo, la tarea que utilizaba el identificador debería congelarse mientras los datos se copiaban de su dirección anterior a la nueva, pero eso no debería llevar mucho tiempo)) Sin embargo, no estoy seguro si eso sucederá alguna vez (Incidentalmente, si tuviera mi druthers, una referencia de objeto sería 32 bits, y un puntero sería una referencia de objeto más un desplazamiento de 32 bits; creo que pasará un tiempo antes de que haya una necesidad de más de 2 mil millones de objetos o de cualquier objeto de más de 4 gigs. A pesar de la Ley de Moore, si una aplicación tuviera más de 2 mil millones de objetos, su desempeño probablemente mejoraría al usar menos objetos más grandes. Si una aplicación necesitara un objeto más de 4 gigas, su desempeño probablemente se mejoraría al usar más objetos más pequeños.)

+0

Interesante punto de vista. Por cierto, ¿2 billones de objetos/4 gb un objeto? En ese momento, puede haber una alternativa a OO en el desarrollo de la secuencia principal, supongo que :-) – rpattabi

+0

"... sería posible que la recolección de basura se realice al mismo tiempo que otras operaciones". La recolección de basura generalmente se realiza al mismo tiempo que otras operaciones. –

+0

@JonHarrop: en un GC "concurrente" típico, gran parte del trabajo del CG se puede hacer simultáneamente con otras operaciones, pero algunas no. Además, intentar que el GC opere simultáneamente con otras operaciones aumenta la sobrecarga del GC, ya que debe hacer un seguimiento de los elementos que pueden haber sido modificados desde la última vez que el GC los examinó. Tener descriptores asistidos por hardware para ayudar a realizar un seguimiento de los objetos que se han modificado podría ayudar en ambos aspectos. – supercat

0

Por lo general, la recolección de basura tiene ciertas desventajas:

  • La recolección de basura consume recursos de computación para decidir lo que ha de ser liberado, la reconstrucción de los hechos que pueden haber sido conocidos por el programador de memoria. La penalización por la conveniencia de no anotar manualmente la duración del objeto en el código fuente es superior, lo que a menudo conduce a un rendimiento reducido o desigual. La interacción con los efectos de jerarquía de memoria puede hacer que esta sobrecarga sea intolerable en circunstancias que son difíciles de predecir o detectar en las pruebas de rutina.
  • El momento en que se recoge realmente la basura puede ser impredecible, lo que da como resultado puestos dispersos a lo largo de una sesión. Los puestos impredecibles pueden ser inaceptables en entornos en tiempo real, como controladores de dispositivos, en el procesamiento de transacciones o en programas interactivos.
  • La memoria puede filtrarse a pesar de la presencia de un recolector de basura, si las referencias a objetos no utilizados no se eliminan manualmente. Esto se describe como una pérdida de memoria lógica. [3] Por ejemplo, los algoritmos recursivos normalmente retrasan la liberación de los objetos de la pila hasta después de que se haya completado la llamada final. El almacenamiento en memoria caché y la memorización, técnicas de optimización comunes, comúnmente conducen a tales fugas lógicas. La creencia de que la recolección de basura elimina todas las fugas lleva a muchos programadores a no protegerse contra la creación de tales fugas.
  • En entornos de memoria virtual típicos de las computadoras de escritorio modernas, puede ser difícil para el recolector de basura saber cuándo es necesaria la recolección, lo que resulta en grandes cantidades de basura acumulada, una fase de recolección larga y disruptiva y otros datos de programas intercambiados .
  • Quizás el problema más importante es que los programas que dependen de recolectores de basura a menudo muestran una ubicación pobre (interactúan mal con caché y sistemas de memoria virtual), ocupan más espacio de direcciones que el programa realmente utiliza en un momento dado y tocan páginas inactivas . Estos pueden combinarse en un fenómeno llamado golpeteo, en el cual un programa pasa más tiempo copiando datos entre varios grados de almacenamiento que realizando un trabajo útil. Pueden hacer que sea imposible para un programador razonar sobre los efectos de rendimiento de las elecciones de diseño, lo que dificulta el ajuste del rendimiento. Pueden conducir programas de recolección de basura para interferir con otros programas que compiten por recursos
+2

Bastante sorprendente que eché de menos consultar la wikipedia para obtener mi pregunta. ¡Gracias! http://en.wikipedia.org/wiki/Garbage_collection_(computer_science)#Disadvantages – rpattabi

+0

"La recolección de basura consume recursos informáticos para decidir qué memoria se liberará". También ahorra recursos al eliminar todas las llamadas a 'gratis'. –

+0

"La memoria puede filtrarse a pesar de la presencia de un recolector de basura". Eso no es una desventaja de la recolección de basura más que el próximo error de programación del que no te salva. –

4

Estoy interesado en saber las limitaciones/desventajas de la aplicación de la escritura en lenguas GCed. Asumiendo que la implementación de GC es óptima, me pregunto si GC nos puede limitar para tomar algunas decisiones de optimización.

Mi creencia es que la gestión automática de la memoria impone un techo de cristal en la eficiencia, pero no tengo pruebas para corroborar eso. En particular, los algoritmos GC actuales ofrecen solo un alto rendimiento o baja latencia, pero no ambos simultáneamente. Los sistemas de producción como .NET y HotSpot JVM incurren en pausas significativas precisamente porque están optimizados para el rendimiento. Los algoritmos especializados de GC como Staccato ofrecen una latencia mucho más baja, pero a costa de una utilización del mutador mínimo mucho menor y, por lo tanto, un bajo rendimiento.

Cuestiones relacionadas