La gestión automática de memoria es posible gracias a Garbage Collection en .NET Framework . Cuando se crea un objeto de clase en tiempo de ejecución, se le asigna cierto espacio de memoria en la memoria del montón. Sin embargo, después de que todas las acciones relacionadas con el objeto se completan en el programa, el espacio de memoria asignado a él es un desperdicio ya que no se puede utilizar. En este caso, la recolección de elementos no utilizados es muy útil, ya que libera automáticamente el espacio de la memoria cuando ya no se necesita.
La recolección de basura siempre funcionará en Managed Heap e internamente tiene un motor que se conoce como motor de optimización .
La recolección de elementos no utilizados se produce si se cumple al menos una de varias condiciones. Estas condiciones se dan de la siguiente manera:
- Si el sistema tiene poca memoria física, entonces es necesaria la recolección de elementos no utilizados.
- Si la memoria asignada a varios objetos en la memoria del montón supera un umbral preestablecido, se produce la recolección de elementos no utilizados.
- Si se llama al método GC.Collect , se produce la recolección de elementos no utilizados. Sin embargo, este método solo se llama en situaciones inusuales, ya que normalmente el recolector de basura se ejecuta automáticamente.
Fases en la recolección de basura
Hay principalmente 3 fases en la recolección de basura. Los detalles sobre estos se dan a continuación:
- Fase de marcado: se crea una lista de todos los objetos vivos durante la fase de marcado. Esto se hace siguiendo las referencias de todos los objetos raíz. Todos los objetos que no están en la lista de objetos activos se eliminan potencialmente de la memoria del montón.
- Fase de reubicación: Las referencias de todos los objetos que estaban en la lista de todos los objetos vivos se actualizan en la fase de reubicación para que apunten a la nueva ubicación donde se reubicarán los objetos en la fase de compactación.
- Fase de compactación: el montón se compacta en la fase de compactación a medida que se libera el espacio ocupado por los objetos muertos y se mueven los objetos vivos restantes. Todos los objetos vivos que quedan después de la recolección de elementos no utilizados se mueven hacia el extremo más antiguo de la memoria del montón en su orden original.
Montón de generaciones en la recolección de basura
La memoria del montón está organizada en 3 generaciones para que varios objetos con diferentes tiempos de vida puedan manejarse adecuadamente durante la recolección de elementos no utilizados. La memoria para cada Generación será dada por Common Language Runtime (CLR) dependiendo del tamaño del proyecto. Internamente, el motor de optimización llamará al método de medios de recopilación para seleccionar qué objetos entrarán en la generación 1 o la generación 2.
- Generación 0: todos los objetos de corta duración, como las variables temporales, están contenidos en la generación 0 de la memoria del montón. Todos los objetos recién asignados también son objetos de generación 0 implícitamente a menos que sean objetos grandes. En general, la frecuencia de recolección de basura es la más alta en la generación 0.
- Generación 1: si el espacio ocupado por algunos objetos de la generación 0 que no se liberan en una ejecución de recolección de basura, estos objetos se mueven a la generación 1. Los objetos de esta generación son una especie de amortiguador entre los objetos de corta duración en la generación 0 y los objetos de larga vida en la generación 2.
- Generación 2: si el espacio ocupado por algunos objetos de la generación 1 que no se liberan en la siguiente ejecución de recolección de elementos no utilizados, estos objetos se mueven a la generación 2. Los objetos de la generación 2 son de larga duración, como los objetos estáticos, ya que permanecen en la memoria del montón. durante toda la duración del proceso.
Nota: La recolección de basura de una generación implica la recolección de basura de todas sus generaciones más jóvenes. Esto significa que se liberan todos los objetos de esa generación en particular y sus generaciones más jóvenes. Por este motivo, la recolección de elementos no utilizados de la generación 2 se denomina recolección de elementos no utilizados completa, ya que se liberan todos los objetos de la memoria del montón. Además, la memoria asignada a la Generación 2 será mayor que la memoria de la Generación 1 y, de manera similar, la memoria de la Generación 1 será mayor que la memoria de la Generación 0 ( Generación 2 > Generación 1 > Generación 0 ).
Un programa que demuestra el número de generaciones de almacenamiento dinámico en la recolección de elementos no utilizados utilizando la propiedad GC.MaxGeneration de la clase GC es el siguiente:
csharp
using System; public class Demo { // Main Method public static void Main(string[] args) { Console.WriteLine("The number of generations are: " + GC.MaxGeneration); } }
The number of generations are: 2
En el programa anterior, la propiedad GC.MaxGeneration se usa para encontrar el número máximo de generaciones que admite el sistema, es decir, 2. Si ejecuta este programa en compiladores en línea, puede obtener resultados diferentes, ya que depende del sistema.
Métodos en la clase GC
La clase GC controla el recolector de basura del sistema. Algunos de los métodos de la clase GC son los siguientes:
Método GC.GetGeneration() : este método devuelve el número de generación del objeto de destino. Requiere un solo parámetro, es decir, el objeto de destino para el que se requiere el número de generación.
Un programa que demuestra el método GC.GetGeneration() es el siguiente:
csharp
using System; public class Demo { public static void Main(string[] args) { Demo obj = new Demo(); Console.WriteLine("The generation number of object obj is: " + GC.GetGeneration(obj)); } }
The generation number of object obj is: 0
Método GC.GetTotalMemory() : este método devuelve el número de bytes que se asignan en el sistema. Requiere un solo parámetro booleano donde verdadero significa que el método espera a que ocurra la recolección de basura antes de regresar y falso significa lo contrario.
Un programa que demuestra el método GC.GetTotalMemory() es el siguiente:
csharp
using System; public class Demo { public static void Main(string[] args) { Console.WriteLine("Total Memory:" + GC.GetTotalMemory(false)); Demo obj = new Demo(); Console.WriteLine("The generation number of object obj is: " + GC.GetGeneration(obj)); Console.WriteLine("Total Memory:" + GC.GetTotalMemory(false)); } }
Total Memory:4197120 The generation number of object obj is: 0 Total Memory:4204024
Nota: La salida puede variar ya que depende del sistema.
Método GC.Collect(): la recolección de basura se puede forzar en el sistema mediante el método GC.Collect() . Este método requiere un solo parámetro, es decir, el número de la generación más antigua para la que se realiza la recolección de elementos no utilizados.
Un programa que demuestra el método GC.Collect() es el siguiente:
csharp
using System; public class Demo { public static void Main(string[] args) { GC.Collect(0); Console.WriteLine("Garbage Collection in Generation 0 is: " + GC.CollectionCount(0)); } }
Garbage Collection in Generation 0 is: 1
Beneficios de la recolección de basura
- Garbage Collection tiene éxito en la asignación de objetos de manera eficiente en la memoria del montón utilizando las generaciones de recolección de elementos no utilizados.
- No se necesita la liberación manual de la memoria, ya que la recolección de elementos no utilizados libera automáticamente el espacio de la memoria cuando ya no se necesita.
- La recolección de basura maneja la asignación de memoria de manera segura para que ningún objeto use el contenido de otro objeto por error.
- Los constructores de objetos recién creados no tienen que inicializar todos los campos de datos, ya que la recolección de elementos no utilizados borra la memoria de los objetos que se liberaron anteriormente.
Publicación traducida automáticamente
Artículo escrito por harkiran78 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA