Conceptos b谩sicos de la gesti贸n de la memoria en Python

    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.

     

    Etiquetas:

    Deja una respuesta

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