significa residuos recolección recoleccion qué que programacion proceso metodos funciona contexto configurar como collector basura java python garbage-collection

residuos - qué significa recolección de basura en el contexto de java



¿Por qué los métodos de recolección de basura de Java y Python son diferentes? (9)

Python usa el método de recuento de referencias para manejar el tiempo de vida del objeto. Entonces un objeto que no tiene más uso será destruido inmediatamente.

Pero, en Java, el GC (recolector de basura) destruye objetos que ya no se usan en un momento específico.

¿Por qué Java elige esta estrategia y cuál es el beneficio de esto?

¿Es esto mejor que el enfoque de Python?


La recolección de basura es más rápida (más eficiente en tiempo) que el recuento de referencias, si tiene suficiente memoria. Por ejemplo, una copia gc atraviesa los objetos "vivos" y los copia en un nuevo espacio, y puede reclamar todos los objetos "muertos" en un solo paso al marcar una región de memoria completa. Esto es muy eficiente, si tiene suficiente memoria. Las colecciones generacionales usan el conocimiento de que "la mayoría de los objetos mueren jóvenes"; a menudo solo se debe copiar un pequeño porcentaje de los objetos.

[Esta es también la razón por la que gc puede ser más rápido que malloc / gratis]

El conteo de referencias es mucho más eficiente en el uso del espacio que la recolección de basura, ya que recupera la memoria en el mismo momento en que se vuelve inalcanzable. Esto es útil cuando desea adjuntar finalizadores a objetos (por ejemplo, para cerrar un archivo una vez que el objeto File no está disponible). Un sistema de conteo de referencias puede funcionar incluso cuando solo un pequeño porcentaje de la memoria es libre. Pero el costo de administración de tener que incrementar y disminuir los contadores en cada asignación de puntero costaba mucho tiempo, y todavía se necesita algún tipo de recolección de basura para reclamar los ciclos.

Por lo tanto, la compensación es clara: si tiene que trabajar en un entorno con limitaciones de memoria, o si necesita finalizadores precisos, utilice el recuento de referencias. Si tiene suficiente memoria y necesita la velocidad, use la recolección de basura.



Darren Thomas da una buena respuesta. Sin embargo, una gran diferencia entre los enfoques de Java y Python es que con el recuento de referencias en el caso común (sin referencias circulares) los objetos se limpian inmediatamente en lugar de en una fecha posterior indeterminada.

Por ejemplo, puedo escribir código descuidado y no portátil en CPython, como

def parse_some_attrs(fname): return open(fname).read().split("~~~")[2:4]

y el descriptor de archivo para ese archivo que abrí se limpiará inmediatamente porque tan pronto como la referencia al archivo abierto se va, el archivo es basura y el descriptor de archivo es liberado. Por supuesto, si ejecuto Jython o IronPython o posiblemente PyPy, el recolector de basura no se ejecutará necesariamente hasta mucho más tarde; posiblemente me quedaré sin descriptores de archivo primero y mi programa se bloqueará.

Entonces, DEBERÍAS escribir código que se vea como

def parse_some_attrs(fname): with open(fname) as f: return f.read().split("~~~")[2:4]

pero a veces a la gente le gusta contar con referencias para liberar siempre sus recursos porque a veces puede hacer que su código sea un poco más corto.

Yo diría que el mejor recolector de basura es el que tiene el mejor rendimiento, que actualmente parece ser el basurero generacional al estilo Java que se puede ejecutar en un hilo separado y tiene todas estas optimizaciones locas, etc. Las diferencias con respecto a cómo usted escriba su código debe ser insignificante e idealmente inexistente.


La última máquina virtual Java de Sun tiene realmente múltiples algoritmos de GC que puede ajustar. Las especificaciones de Java VM omitieron intencionalmente el comportamiento real del GC para permitir diferentes (y múltiples) algoritmos GC para diferentes máquinas virtuales.

Por ejemplo, para todas las personas a las que no les gusta el enfoque de "pare el mundo" del comportamiento predeterminado del Sun Java VM GC, hay VM como WebSphere Real Time de IBM que permite que la aplicación en tiempo real se ejecute en Java.

Como la especificación Java VM está públicamente disponible, (en teoría) nada impide que alguien implemente una VM Java que use el algoritmo GC de CPython.


El conteo de referencias es particularmente difícil de hacer eficientemente en un entorno de subprocesos múltiples. No sé cómo comenzarías a hacerlo sin entrar en transacciones asistidas por hardware o instrucciones atómicas similares (actualmente) inusuales.

El recuento de referencias es fácil de implementar. Las JVM han invertido mucho dinero en implementaciones competidoras, por lo que no debería sorprender que implementen soluciones muy buenas para problemas muy difíciles. Sin embargo, cada vez es más fácil orientar su idioma favorito a la JVM.


En realidad, el recuento de referencias y las estrategias utilizadas por Sun JVM son todos tipos diferentes de algoritmos de recolección de basura.

Hay dos enfoques amplios para rastrear objetos muertos: rastreo y recuento de referencias. Al rastrear el GC comienza desde las "raíces", cosas como las referencias a la pila, y rastrea todos los objetos alcanzables (en vivo). Todo lo que no se puede alcanzar se considera muerto. En el recuento de referencias cada vez que se modifica una referencia, el objeto involucrado tiene su conteo actualizado. Cualquier objeto cuya cuenta de referencia se establece en cero se considera muerto.

Básicamente, todas las implementaciones de GC tienen compensaciones, pero el rastreo generalmente es bueno para operaciones de alto rendimiento (es decir, rápidas) pero tiene tiempos de pausa más largos (brechas más grandes donde la IU o el programa pueden congelarse). El recuento de referencias puede operar en trozos más pequeños, pero será más lento en general. Puede significar menos congelaciones pero peor rendimiento en general.

Además, un GC de recuento de referencias requiere un detector de ciclos para limpiar cualquier objeto en un ciclo que no sea capturado solo por su recuento de referencia. Perl 5 no tenía un detector de ciclo en su implementación de GC y podría perder memoria que era cíclica.

También se han realizado investigaciones para obtener lo mejor de ambos mundos (tiempos de pausa bajos, alto rendimiento): http://cs.anu.edu.au/~Steve.Blackburn/pubs/papers/urc-oopsla-2003.pdf


Tarde en el juego, pero creo que una razón importante para RC en python es su simplicidad. Vea este correo electrónico de Alex Martelli , por ejemplo.

(No pude encontrar un enlace fuera de la memoria caché de Google, la fecha del correo electrónico desde el 13 de octubre de 2005 en la lista de Python).


Existen desventajas de usar el conteo de referencias. Una de las más mencionadas es referencias circulares: supongamos que A referencias B, B referencias C y C referencias B. Si A fuera a soltar su referencia a B, tanto B como C seguirán teniendo un recuento de referencia de 1 y no serán borrados con el recuento de referencia tradicional. CPython (el recuento de referencias no es parte de Python en sí, sino parte de la implementación C del mismo) capta referencias circulares con una rutina de recolección de basura separada que se ejecuta periódicamente ...

Otro inconveniente: el recuento de referencias puede hacer que la ejecución sea más lenta. Cada vez que se hace referencia y se quita la referencia a un objeto, el intérprete / VM debe verificar si el recuento se ha reducido a 0 (y luego desasignar si lo hizo). Garbage Collection no necesita hacer esto.

Además, la recolección de basura se puede hacer en un hilo separado (aunque puede ser un poco complicado). En máquinas con mucha RAM y para procesos que usan la memoria solo lentamente, es posible que no desee hacer GC en absoluto. El recuento de referencias sería un inconveniente allí en términos de rendimiento ...


Una gran desventaja de la GC de rastreo de Java es que de vez en cuando "parará el mundo" y congelará la aplicación por un tiempo relativamente largo para hacer un GC completo. Si el montón es grande y el árbol de objetos complejo, se congelará durante unos segundos. Además, cada GC completo visita todo el árbol de objetos una y otra vez, algo que probablemente sea bastante ineficiente. Otro inconveniente de la forma en que Java hace GC es que debe decirle a jvm qué tamaño de almacenamiento dinámico desea (si el valor predeterminado no es lo suficientemente bueno); la JVM deriva de ese valor varios umbrales que dispararán el proceso GC cuando hay demasiada acumulación de basura en el montón.

Supongo que esta es la causa principal de la sensación desigual de Android (basada en Java), incluso en los teléfonos celulares más caros, en comparación con la suavidad de iOS (basado en ObjectiveC y el uso de RC).

Me encantaría ver una opción jvm para habilitar la administración de la memoria RC, y quizás mantener GC solo para ejecutar como último recurso cuando ya no quede más memoria.