Conceptos básicos de la gestión de la memoria en Python

C

Introducción

La administración de la memoria es el proceso de asignar, desasignar y coordinar la memoria de manera eficiente para que todos los diferentes procesos se ejecuten sin problemas y puedan acceder de manera óptima a los diferentes recursos del sistema. La gestión de la memoria también implica limpiar la memoria de los objetos a los que ya no se accede.

En Python, el administrador de memoria es responsable de este tipo de tareas ejecutándose periódicamente para limpiar, asignar y administrar la memoria. A diferencia de C, Java y otros lenguajes de programación, Python administra objetos mediante el recuento de referencias. Esto significa que el administrador de memoria realiza un seguimiento del número de referencias a cada objeto en el programa. Cuando el recuento de referencias de un objeto cae a cero, lo que significa que el objeto ya no se usa, el recolector de basura (parte del administrador de memoria) automáticamente libera la memoria de ese objeto en particular.

El usuario no debe preocuparse por la gestión de la memoria, ya que el proceso de asignación y desasignación de memoria es completamente automático. La memoria recuperada puede ser utilizada por otros objetos.

Recolección de basura de Python

Como se explicó anteriormente, Python elimina los objetos a los que ya no se hace referencia en el programa para liberar espacio en la memoria. Este proceso en el que Python libera bloques de memoria que ya no se utilizan se llama Garbage Collection. El python Recolector de basura (GC) se ejecuta durante la ejecución del programa y se activa si el recuento de referencia se reduce a cero. El recuento de referencias aumenta si a un objeto se le asigna un nuevo nombre o se coloca en un contenedor, como una tupla o un diccionario. De manera similar, el recuento de referencias disminuye cuando se reasigna la referencia a un objeto, cuando la referencia del objeto queda fuera de alcance o cuando se elimina un objeto.

La memoria es un montón que contiene objetos y otras estructuras de datos que se utilizan en el programa. El administrador de memoria de Python controla la asignación y desasignación de este espacio de almacenamiento mediante el uso de funciones API.

Objetos de Python en la memoria

Cada variable en Python actúa como un objeto. Los objetos pueden ser simples (que contienen números, cadenas, etc.) o contenedores (diccionarios, listas o clases definidas por el usuario). Además, Python es un lenguaje escrito dinámicamente, lo que significa que no necesitamos declarar las variables o sus tipos antes de usarlas en un programa.

Por ejemplo:

>>> x = 5
>>> print(x)
5
>>> del x
>>> print(x)
Traceback (most reent call last):
  File "<mem_manage>", line 1, in <module>
    print(x)
NameError : name 'x' is not defined

Si observa las primeras 2 líneas del programa anterior, objete x es conocida. Cuando borramos el objeto x e intentamos usarlo, obtenemos un error que indica que la variable x no está definido.

Puede ver que la recolección de basura en Python está completamente automatizada y el programador no necesita preocuparse por ello, a diferencia de lenguajes como C.

Modificar el recolector de basura

El recolector de basura de Python tiene tres generaciones en las que se clasifican los objetos. Un nuevo objeto en el punto de partida de su ciclo de vida es la primera generación del recolector de basura. A medida que el objeto sobreviva a la recolección de basura, se moverá a las siguientes generaciones. Cada una de las 3 generaciones del recolector de basura tiene un umbral. Específicamente, cuando se excede el umbral del número de asignaciones menos el número de desasignaciones, esa generación ejecutará la recolección de basura.

Las generaciones anteriores también son basura recolectada con más frecuencia que las generaciones superiores. Esto se debe a que es más probable que se descarten los objetos más nuevos que los viejos.

los gc El módulo incluye funciones para cambiar el valor de umbral, activar un proceso de recolección de basura manualmente, deshabilitar el proceso de recolección de basura, etc. Podemos verificar los valores de umbral de diferentes generaciones del recolector de basura usando el get_threshold() método:

import gc
print(gc.get_threshold())

Salida de muestra:

(700, 10, 10)

Como puede ver, aquí tenemos un umbral de 700 para la primera generación y de 10 para cada una de las otras dos generaciones.

Podemos alterar el valor de umbral para activar el proceso de recolección de basura usando el set_threshold() método del gc módulo:

gc.set_threshold(900, 15, 15)

En el ejemplo anterior, hemos aumentado el valor de umbral para las 3 generaciones. El aumento del valor de umbral disminuirá la frecuencia de ejecución del recolector de basura. Normalmente, no necesitamos pensar demasiado en la recolección de basura de Python como desarrollador, pero esto puede ser útil al optimizar el tiempo de ejecución de Python para su sistema de destino. Uno de los beneficios clave es que el mecanismo de recolección de basura de Python maneja una gran cantidad de detalles de bajo nivel para el desarrollador automáticamente.

¿Por qué realizar la recolección de basura manual?

Sabemos que el intérprete de Python realiza un seguimiento de las referencias a los objetos utilizados en un programa. En versiones anteriores de Python (hasta la versión 1.6), el intérprete de Python usaba solo el mecanismo de conteo de referencias para manejar la memoria. Cuando el recuento de referencias cae a cero, el intérprete de Python libera automáticamente la memoria. Este mecanismo clásico de recuento de referencias es muy eficaz, excepto que no funciona cuando el programa tiene ciclos de referencia. Se produce un ciclo de referencia si se hace referencia a uno o más objetos entre sí y, por lo tanto, el recuento de referencias nunca llega a cero.

Consideremos un ejemplo.

>>> def create_cycle():
...     list = [8, 9, 10]
...     list.append(list)
...     return list
... 
>>> create_cycle()
[8, 9, 10, [...]]

El código anterior crea un ciclo de referencia, donde el objeto list se refiere a sí mismo. Por tanto, la memoria del objeto list no se liberará automáticamente cuando vuelva la función. El problema del ciclo de referencia no se puede resolver contando referencias. Sin embargo, este problema del ciclo de referencia se puede resolver cambiando el comportamiento del recolector de basura en su aplicación Python.

Para hacerlo, podemos usar el gc.collect() función de la gc módulo.

import gc
n = gc.collect()
print("Number of unreachable objects collected by GC:", n)

los gc.collect() devuelve el número de objetos que ha recopilado y desasignado.

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

La recolección de basura basada en el tiempo es bastante simple: gc.collect() La función se llama después de un intervalo de tiempo fijo.

La recolección de basura basada en eventos llama al gc.collect() funciona después de que ocurre un evento (es decir, cuando se sale de la aplicación o la aplicación permanece inactiva durante un período de tiempo específico).

Comprendamos el trabajo de recolección de basura manual creando algunos ciclos de referencia.

import sys, gc

def create_cycle():
    list = [8, 9, 10]
    list.append(list)

def main():
    print("Creating garbage...")
    for i in range(8):
        create_cycle()

    print("Collecting...")
    n = gc.collect()
    print("Number of unreachable objects collected by GC:", n)
    print("Uncollectable garbage:", gc.garbage)

if __name__ == "__main__":
    main()
    sys.exit()

La salida es la siguiente:

Creating garbage...
Collecting...
Number of unreachable objects collected by GC: 8
Uncollectable garbage: []

El script anterior crea un objeto de lista al que hace referencia una variable, denominada de forma creativa list. El primer elemento del objeto de lista se refiere a sí mismo. El recuento de referencias del objeto de lista es siempre mayor que cero, incluso si se elimina o está fuera del alcance del programa. Por lo tanto, la list El objeto no es basura recolectada debido a la referencia circular. El mecanismo del recolector de basura en Python buscará y recopilará automáticamente referencias circulares periódicamente.

En el código anterior, como el recuento de referencias es al menos 1 y nunca puede llegar a 0, hemos recolectado de manera forzosa los objetos llamando gc.collect(). Sin embargo, recuerde no forzar la recolección de basura con frecuencia. La razón es que incluso después de liberar la memoria, el GC necesita tiempo para evaluar la elegibilidad del objeto para ser recolectado como basura, lo que consume tiempo y recursos del procesador. Además, recuerde administrar manualmente el recolector de basura solo después de que su aplicación se haya iniciado por completo.

Conclusión

En este artículo, discutimos cómo la administración de memoria en Python se maneja automáticamente mediante el uso de estrategias de conteo de referencias y recolección de basura. Sin recolección de basura, implementar un mecanismo de administración de memoria exitoso en Python es imposible. Además, los programadores no deben preocuparse por eliminar la memoria asignada, ya que el administrador de memoria de Python se encarga de ello. Esto conduce a menos pérdidas de memoria y a un mejor rendimiento.

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad