Recolección de basura en Python

El método de asignación y desasignación de memoria de Python es automático. El usuario no tiene que preasignar o desasignar memoria de forma similar al uso de la asignación de memoria dinámica en lenguajes como C o C++. 
Python utiliza dos estrategias para la asignación de memoria: 

  • Recuento de referencias
  • Recolección de basura

Antes de la versión 2.0 de Python, el intérprete de Python solo usaba el conteo de referencias para la administración de la memoria. El recuento de referencias funciona contando el número de veces que otros objetos del sistema hacen referencia a un objeto. Cuando se eliminan las referencias a un objeto, se reduce el recuento de referencias de un objeto. Cuando el recuento de referencias llega a cero, el objeto se desasigna. Ex- 

Python

# Literal 9 is an object
b = 9
 
# Reference count of object 9
# becomes 0.
b = 4

El valor literal 9 es un objeto. El conteo de referencia del objeto 9 se incrementa a 1 en la línea 1. En la línea 2, su conteo de referencia se convierte en cero a medida que se elimina la referencia. Entonces el recolector de basura desasigna el objeto.
Se crea un ciclo de referencia cuando no hay forma de que el recuento de referencia del objeto pueda alcanzar. Los ciclos de referencia que involucran listas, tuplas, instancias, clases, diccionarios y funciones son comunes. La forma más sencilla de crear un ciclo de referencia es crear un objeto que se refiera a sí mismo, como en el siguiente ejemplo: 

Python

def create_cycle():
 
    # create a list x
    x = [ ]
 
    # A reference cycle is created
    # here as x contains reference to
    # to self.
    x.append(x)
  
create_cycle()

Debido a que create_cycle() crea un objeto x que se refiere a sí mismo, el objeto x no se liberará automáticamente cuando la función regrese. Esto hará que la memoria que usa x se mantenga hasta que se invoque el recolector de elementos no utilizados de Python.

Formas de hacer que un objeto sea elegible para la recolección de basura

Python

x = []
x.append(l)
x.append(2)
 
# delete the list from memory or
# assigning object x to None(Null)
del x
# x = None

El recuento de referencias para la lista creada ahora es dos. Sin embargo, dado que no se puede acceder a él desde el interior de Python y posiblemente no se pueda volver a utilizar, se considera basura. En la versión actual de Python, esta lista nunca se libera. 
 

Recolección Automática de Basura de Ciclos

Debido a que los ciclos de referencia requieren trabajo computacional para descubrirlos, la recolección de elementos no utilizados debe ser una actividad programada. Python programa la recolección de basura en función de un umbral de asignaciones de objetos y desasignaciones de objetos. Cuando el número de asignaciones menos el número de desasignaciones es mayor que el número de umbral, se ejecuta el recolector de elementos no utilizados. Uno puede inspeccionar el umbral para nuevos objetos (objetos en Python conocidos como objetos de generación 0) importando el módulo gc y solicitando umbrales de recolección de basura: 
 

Python

# loading gc
import gc
 
# get the current collection
# thresholds as a tuple
print("Garbage collection thresholds:",
                    gc.get_threshold())

Producción: 

Garbage collection thresholds: (700, 10, 10) 

Aquí, el umbral predeterminado en el sistema anterior es 700. Esto significa que cuando la cantidad de asignaciones frente a la cantidad de desasignaciones es superior a 700, se ejecutará el recolector de basura automático. Por lo tanto, cualquier parte de su código que libere grandes bloques de memoria es un buen candidato para ejecutar la recolección de basura manual. 
 

Recolección manual de basura

Invocar el recolector de basura manualmente durante la ejecución de un programa puede ser una buena idea sobre cómo manejar la memoria consumida por los ciclos de referencia. 
La recolección de basura se puede invocar manualmente de la siguiente manera: 

Python

# Importing gc module
import gc
 
# Returns the number of
# objects it has collected
# and deallocated
collected = gc.collect()
 
# Prints Garbage collector
# as 0 object
print("Garbage collector: collected",
          "%d objects." % collected)

Producción:

('Garbage collector: collected', '0 objects.')

Si se crean pocos ciclos, entonces cómo funciona la recolección manual: 
Ejemplo: 

Python

import gc
i = 0
 
# create a cycle and on each iteration x as a dictionary
# assigned to 1
def create_cycle():
    x = { }
    x[i+1] = x
    print x
 
# lists are cleared whenever a full collection or
# collection of the highest generation (2) is run
collected = gc.collect() # or gc.collect(2)
print "Garbage collector: collected %d objects." % (collected)
 
print "Creating cycles..."
for i in range(10):
    create_cycle()
 
collected = gc.collect()
 
print "Garbage collector: collected %d objects." % (collected)

Producción: 

Garbage collector: collected 0 objects.
Creating cycles...
{1: {...}}
{2: {...}}
{3: {...}}
{4: {...}}
{5: {...}}
{6: {...}}
{7: {...}}
{8: {...}}
{9: {...}}
{10: {...}}
Garbage collector: collected 10 objects.

Hay dos formas de realizar la recolección de basura manual: recolección de basura basada en tiempo y basada en eventos. 

  1. La recolección de basura basada en el tiempo es simple: se llama al recolector de basura después de un intervalo de tiempo fijo. 
  2. La recolección de elementos no utilizados basada en eventos llama al recolector de elementos no utilizados cuando ocurre un evento. Por ejemplo, cuando un usuario sale de la aplicación o cuando la aplicación entra en estado inactivo. 
     

Referencia 

Publicación traducida automáticamente

Artículo escrito por AFZAL ANSARI y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *