¿Cómo funciona el mecanismo de recolección de basura?

En una terminología de hombre común, ¿cómo funciona el mecanismo de recolección de basura?

¿Cómo se identifica que un objeto está disponible para la recolección de basura?

Además, ¿qué significa Reference Counting, Mark and Sweep, Copying, Train en algoritmos GC?

Cuando utiliza un lenguaje con recolección de basura no tendrá acceso a la memoria directamente. Más bien, se te da acceso a cierta abstracción sobre esos datos. Una de las cosas que se abstrae correctamente es la ubicación real en la memoria del bloque de datos, así como punteros a otros bloques de datos. Cuando se ejecuta el recolector de elementos no utilizados (esto ocurre de vez en cuando), comprobará si aún tiene una referencia a cada uno de los bloques de memoria que le ha asignado. Si no lo hace, liberará esa memoria.

La principal diferencia entre los diferentes tipos de recolectores de basura es su eficiencia así como también cualquier limitación sobre qué tipo de esquemas de asignación pueden manejar.

El más simple es el recuento de referencia adecuado. Cada vez que crea una referencia a un objeto, se incrementa un contador interno en ese objeto, cuando hace la referencia o deja de estar en el scope, el contador en el (anterior) objeto objective se reduce. Cuando este contador llega a cero, el objeto ya no se remite y puede liberarse.

El problema con el recuento de basureros de referencia es que no pueden tratar con datos circulares. Si el objeto A tiene una referencia al objeto B y que a su vez tiene alguna referencia (directa o indirecta) al objeto A, nunca podrán liberarse, incluso si ninguno de los objetos de la cadena está arbitrado fuera de la cadena (y por lo tanto no lo son). t accesible para el progtwig en absoluto).

El algoritmo Mark and sweep por otro lado puede manejar esto. El algoritmo de marca y barrido funciona al detener periódicamente la ejecución del progtwig, marcar cada elemento que el progtwig ha asignado como inalcanzable. El progtwig luego ejecuta todas las variables que tiene el progtwig y marca lo que señalan como alcanzable. Si cualquiera de estas asignaciones contiene referencias a otros datos en el progtwig, esos datos también se marcan como accesibles, etc.

Esta es la parte de marca del algoritmo. En este punto, todo lo que el progtwig puede acceder, sin importar cuán indirectamente, se marque como alcanzable y todo lo que el progtwig no puede alcanzar se marca como inalcanzable. El recolector de basura ahora puede reclamar de forma segura la memoria asociada con los objetos marcados como inalcanzables.

El problema con el algoritmo de marca y barrido es que no es tan eficiente: todo el progtwig debe detenerse para ejecutarlo, y muchas de las referencias a objetos no van a cambiar.

Para mejorar esto, el algoritmo de marca y barrido se puede extender con la llamada “recolección de basura generacional”. En este modo, los objetos que han estado en el sistema para cierto número de colecciones de basura se promueven a la generación anterior, que no se comprueba con tanta frecuencia.

Esto mejora la eficiencia porque los objetos tienden a morir jóvenes (piense en una cadena que se cambia dentro de un bucle, lo que resulta quizás una vida de unos pocos cientos de ciclos) o viva mucho tiempo (los objetos utilizados para representar la ventana principal de una aplicación, o conexión de base de datos de un servlet).

Se puede encontrar mucha más información detallada en wikipedia.

Agregado basado en comentarios:

Con el algoritmo de marcaje y barrido (así como cualquier otro algoritmo de recolección de basura, excepto el recuento de referencias), la recolección de basura no se ejecuta en el contexto de su progtwig, ya que debe poder acceder a cosas a las que su progtwig no puede acceder directamente. . Por lo tanto, no es correcto decir que el recolector de basura se ejecuta en la stack.

  • Recuento de referencias: cada objeto tiene un recuento que se incrementa cuando alguien toma una referencia al objeto, y disminuye cuando alguien suelta la referencia. Cuando el recuento de referencias va a cero, el objeto se elimina. COM usa este enfoque.
  • Marcar y barrer: cada objeto tiene una bandera si está en uso. Comenzando en la raíz del gráfico del objeto (variables globales, locals en stacks, etc.) cada objeto referenciado obtiene su bandera establecida, y así sucesivamente en la cadena. Al final, se eliminan todos los objetos que no están referenciados en el gráfico.

El recolector de basura para el CLR se describe en esta diapositiva . “Roots” en la diapositiva 15 son las fonts de los objetos que entran primero en el gráfico. Sus campos de miembros, etc., se usan para buscar otros objetos en el gráfico.

Wikipedia describe varios de estos enfoques en mucho más y mejor detalle.

La recolección de basura es simplemente saber si hay alguna necesidad futura de variables en su progtwig y, de no ser así, recostackrlas y eliminarlas.

Énfasis en la palabra Basura , algo que está completamente usado en su casa es tirado a la basura y el basurero lo maneja viniendo a recogerlo y llevándolo para darle más espacio en la basura de su casa.

El recuento de referencias, la marca y el barrido, la copia, el tren, etc. se discuten con detalle en las preguntas frecuentes de GC.

La forma general en que se hace es que el número de referencias a un objeto se mantiene en segundo plano, y cuando ese número va a cero, el objeto está SUJETO A recolección de basura, sin embargo, el GC no se activará hasta que sea explícitamente necesario porque es una operación costosa. Lo que sucede cuando comienza es que el GC pasa por el área de memoria administrada y encuentra todos los objetos que no tienen referencias. El gc borra esos objetos llamando primero a sus destructores, permitiéndoles limpiarlos y luego libera la memoria. Comúnmente, el GC compactará el área de memoria administrada moviendo todos los objetos supervivientes a un área de la memoria, permitiendo que se realicen más asignaciones.

Como dije, este es un método que conozco, y se están haciendo muchas investigaciones en esta área.

La recolección de basura es un gran tema, y ​​hay muchas maneras de implementarlo.

Pero para el más común en pocas palabras, el recolector de basura mantiene un registro de todas las referencias a cualquier cosa creada a través del new operador, incluso si el uso del operador estaba oculto para usted (por ejemplo, en un método Type.Create() ). Cada vez que agrega una nueva referencia al objeto, la raíz de esa referencia se determina y se agrega a la lista, si es necesario. Se elimina una referencia cada vez que sale del scope.

Cuando no hay más referencias a un objeto, puede (no “será”) ser recolectado. Para mejorar el rendimiento y garantizar que la limpieza necesaria se realice correctamente, las colecciones se agrupan para varios objetos a la vez y se producen a lo largo de varias generaciones.