¿ Javascript tiene pérdidas de memoria ? Si es así, ¿cómo evitarlo? En vista de que varias personas me han hecho preguntas similares recientemente, parece que nadie ha estudiado sistemáticamente esta parte del contenido, por lo que planeo compartir con ustedes algo de información que recopilé hace unos años.
En primer lugar, se puede decir con certeza que algunas formas de escribir JavaScript provocarán pérdidas de memoria, al menos en IE6. Por lo tanto, hoy, cuando IE6 se niega a retirarse, todavía necesitamos comprender el conocimiento relevante (aunque en la mayoría de los casos, la pérdida de memoria causada por js no es la razón principal para ralentizar la computadora). La investigación relevante se concentra principalmente en los años 2005-07. Este artículo no tiene ninguna idea nueva. Si tienes amigos que lo hayan estudiado en ese entonces, puedes simplemente ignorarlo.
Como desarrollador front-end, al comprender estos problemas, necesita saber cuáles son y por qué. Por lo tanto, antes de presentar las pérdidas de memoria js, comencemos con el motivo de las pérdidas de memoria.
Cuando hablamos de pérdidas de memoria, tenemos que hablar de la forma en que se asigna la memoria. Hay tres formas de asignar memoria, a saber:
1. Asignación estática: la forma de asignación de variables estáticas y variables globales. Si pensamos en una habitación como un programa, podemos pensar en la memoria asignada estáticamente como un mueble duradero en la habitación. Por lo general, no es necesario liberarlos ni reciclarlos porque nadie tira los armarios por la ventana como basura todos los días.
2. Asignación automática: un método para asignar memoria para variables locales en la pila. La memoria en la pila se puede liberar automáticamente con la operación pop cuando sale el bloque de código.
Esto es similar a las personas que vienen a una habitación para hacer cosas, una vez hechas, se irán solas y el espacio que ocupan se liberará automáticamente cuando estas personas se vayan.
3. Asignación dinámica: un método para asignar dinámicamente espacio de memoria en el montón para almacenar datos. Es decir, la memoria solicitada usando malloc o new cuando el programa se está ejecutando, debemos liberarla nosotros mismos usando free o eliminar. La vida útil de la memoria dinámica la determina el programador. Una vez que olvide liberarlo, inevitablemente provocará una pérdida de memoria. En este caso, los bloques de memoria del montón son como las servilletas que usamos todos los días. Después de usarlas, tenemos que tirarlas a la basura, de lo contrario la casa quedará hecha un desastre. Por eso, los perezosos sueñan con tener un robot doméstico que limpie con ellos. En el desarrollo de software, si es demasiado vago para liberar memoria, también necesita un robot similar, que en realidad es un recolector de basura implementado mediante un algoritmo específico. Son precisamente algunos defectos en el propio mecanismo de recolección de basura los que provocan pérdidas de memoria de JavaScript.
Hace unos años, leí un artículo llamado "Una interesante historia del reciclaje de basura", que explicaba en profundidad el mecanismo de recolección de basura.
Al igual que la sobrealimentación, una tecnología utilizada por muchos automóviles de lujo como punto de venta, que en realidad fue utilizada por Mercedes-Benz en la década de 1910, la tecnología de reciclaje de basura existe desde hace mucho tiempo. El lenguaje Lisp, nacido en el MIT alrededor de 1960, fue el primer lenguaje que dependía en gran medida de la tecnología de asignación de memoria dinámica. Casi todos los datos en Lisp aparecen en forma de "tablas" y el espacio ocupado por las "tablas" está en el montón. asignados dinámicamente. La característica innata de administración de memoria dinámica del lenguaje Lisp requiere que los diseñadores del lenguaje Lisp resuelvan el problema de la liberación automática de cada bloque de memoria en el montón (de lo contrario, los programadores de Lisp inevitablemente se verán abrumados por innumerables declaraciones de liberación o eliminación en el programa). Esto condujo directamente al nacimiento y desarrollo de la tecnología de recolección de basura.
Los tres algoritmos de recolección de basura más básicos también aparecieron juntos en ese momento. Veámoslos uno por uno:
Algoritmo de conteo de referencias: este puede ser el primer método que me viene a la mente. En sentido figurado, el recuento de referencias se puede entender de esta manera. Hay muchos papeles blancos en la casa, y estos papeles son como recuerdos. Usar la memoria es como escribir en estos pedazos de papel. La memoria se puede usar a voluntad, pero hay una condición. Cualquiera que use una hoja de papel debe escribir una cuenta de 1 en la esquina del papel. Si dos personas usan una hoja de papel al mismo tiempo, la cuenta se convierte en. 2, y así sucesivamente. Cuando una persona termina de usar un trozo de papel, el conteo en la esquina debe disminuir en 1. De esta manera, una vez que el conteo llega a 0, se cumplen las condiciones de recolección de basura y el robot que espera a un lado inmediatamente arrojará el papel al caja de basura. El recolector de basura basado en contadores de referencia se ejecuta más rápido, no interrumpe la ejecución del programa durante mucho tiempo y es adecuado para programas que deben ejecutarse en tiempo real. Sin embargo, el contador de referencias aumenta la sobrecarga de ejecución del programa; al mismo tiempo, existe otro problema importante. Este algoritmo tiene un defecto, es decir, una vez que se genera una referencia circular, se perderá memoria. Por ejemplo, nuevos dos objetos a y b. En este momento, los recuentos de a y b son ambos 1. Luego, señalamos un atributo de a a b y un atributo de b a a. En la relación de referencia, los recuentos de a y b se convierten en 2. Cuando el programa finaliza y sale del alcance, el programa automáticamente disminuye el recuento de a en 1. Dado que el recuento de a al final sigue siendo 1, a no será liberado De manera similar, el recuento final de b también es 1, b no se liberará y la memoria simplemente se filtró.