stringtranslate.com

Recolección de basura (informática)

Recolección de basura con parada y copia en una arquitectura Lisp : [1] La memoria se divide en memoria de trabajo y libre ; los objetos nuevos se asignan en la primera. Cuando está llena (como se muestra en la imagen), se realiza la recolección de basura: todas las estructuras de datos que aún están en uso se localizan mediante el rastreo de punteros y se copian en ubicaciones consecutivas en la memoria libre.
Después de esto, el contenido de la memoria de trabajo se descarta a favor de la copia comprimida, y los roles de la memoria de trabajo y la libre se intercambian (se muestra).

En informática , la recolección de basura ( GC ) es una forma de gestión automática de memoria . [2] El recolector de basura intenta recuperar la memoria que fue asignada por el programa, pero que ya no está referenciada; dicha memoria se llama basura . La recolección de basura fue inventada por el científico informático estadounidense John McCarthy alrededor de 1959 para simplificar la gestión manual de la memoria en Lisp . [3]

La recolección de basura libera al programador de realizar una gestión manual de la memoria , donde el programador especifica qué objetos desasignar y devolver al sistema de memoria y cuándo hacerlo. [4] Otras técnicas similares incluyen la asignación de pila , la inferencia de región y la propiedad de la memoria, y combinaciones de las mismas. La recolección de basura puede ocupar una proporción significativa del tiempo total de procesamiento de un programa y, como resultado, afectar el rendimiento .

Los recursos distintos de la memoria, como los sockets de red , los manejadores de bases de datos , las ventanas , los descriptores de archivos y los descriptores de dispositivos, no suelen ser manejados por la recolección de basura, sino por otros métodos (por ejemplo, los destructores ). Algunos de estos métodos también desasignan memoria.

Descripción general

Muchos lenguajes de programación requieren recolección de basura, ya sea como parte de la especificación del lenguaje (por ejemplo, RPL , Java , C# , D , [5] Go y la mayoría de los lenguajes de script ) o de manera efectiva para la implementación práctica (por ejemplo, lenguajes formales como el cálculo lambda ). [6] Se dice que estos son lenguajes de recolección de basura . Otros lenguajes, como C y C++ , fueron diseñados para su uso con administración manual de memoria, pero tienen implementaciones de recolección de basura disponibles. Algunos lenguajes, como Ada , Modula-3 y C++/CLI , permiten que tanto la recolección de basura como la administración manual de memoria coexistan en la misma aplicación mediante el uso de montones separados para objetos recolectados y administrados manualmente. Aún otros, como D , son de recolección de basura pero permiten al usuario eliminar objetos manualmente o incluso deshabilitar la recolección de basura por completo cuando se requiere velocidad. [7]

Aunque muchos lenguajes integran el GC en su compilador y sistema de ejecución , también existen sistemas de GC post-hoc , como el conteo automático de referencias (ARC). Algunos de estos sistemas de GC post-hoc no requieren recompilación. [8]

Ventajas

GC libera al programador de la tarea de desasignar memoria manualmente, lo que ayuda a evitar algunos tipos de errores : [9]

Desventajas

GC utiliza recursos informáticos para decidir qué memoria liberar. Por lo tanto, la penalización por la conveniencia de no anotar la duración de los objetos manualmente en el código fuente es la sobrecarga , que puede perjudicar el rendimiento del programa. [12] Un artículo revisado por pares de 2005 concluyó que GC necesita cinco veces la memoria para compensar esta sobrecarga y funcionar tan rápido como el mismo programa utilizando una gestión de memoria explícita idealizada. Sin embargo, la comparación se realiza con un programa generado insertando llamadas de desasignación utilizando un oráculo , implementado mediante la recopilación de rastros de programas ejecutados bajo un generador de perfiles , y el programa solo es correcto para una ejecución particular del programa. [13] La interacción con los efectos de la jerarquía de memoria puede hacer que esta sobrecarga sea intolerable en circunstancias que son difíciles de predecir o detectar en pruebas de rutina. El impacto en el rendimiento fue dado por Apple como una razón para no adoptar la recolección de basura en iOS , a pesar de ser la característica más deseada. [14]

El momento en que se recolecta la basura puede ser impredecible, lo que da como resultado bloqueos (pausas para cambiar/liberar memoria) dispersos a lo largo de una sesión . Los bloqueos impredecibles pueden ser inaceptables en entornos de tiempo real , en el procesamiento de transacciones o en programas interactivos. Los recolectores de basura incrementales, concurrentes y en tiempo real abordan estos problemas, con diferentes compensaciones.

Estrategias

Rastreo

El rastreo de la recolección de basura es el tipo más común de recolección de basura, tanto que "recolección de basura" a menudo se refiere al rastreo de la recolección de basura, en lugar de otros métodos como el conteo de referencias . La estrategia general consiste en determinar qué objetos deben ser recolectados como basura rastreando qué objetos son accesibles por una cadena de referencias desde ciertos objetos raíz, y considerando el resto como basura y recolectándolos. Sin embargo, hay una gran cantidad de algoritmos utilizados en la implementación, con características de complejidad y rendimiento muy variables.

Recuento de referencias

La recolección de basura por conteo de referencias es cuando cada objeto tiene un recuento de la cantidad de referencias a él. La basura se identifica por tener un recuento de referencias de cero. El recuento de referencias de un objeto se incrementa cuando se crea una referencia a él y se decrementa cuando se destruye una referencia. Cuando el recuento llega a cero, se recupera la memoria del objeto. [15]

Al igual que con la gestión manual de memoria, y a diferencia del seguimiento de la recolección de basura, el conteo de referencias garantiza que los objetos se destruyan tan pronto como se destruye su última referencia y, por lo general, solo accede a la memoria que se encuentra en cachés de CPU , en objetos que se liberarán o directamente apuntados por estos y, por lo tanto, tiende a no tener efectos secundarios negativos significativos en el funcionamiento de la memoria caché de la CPU y la memoria virtual .

El recuento de referencias tiene varias desventajas; por lo general, esto se puede solucionar o mitigar mediante algoritmos más sofisticados:

Ciclos
Si dos o más objetos se refieren entre sí, pueden crear un ciclo por el cual ninguno será recolectado ya que sus referencias mutuas nunca dejan que sus recuentos de referencia se vuelvan cero. Algunos sistemas de recolección de basura que utilizan el recuento de referencias (como el de CPython ) utilizan algoritmos específicos de detección de ciclos para lidiar con este problema. [16] Otra estrategia es usar referencias débiles para los "retropunteros" que crean ciclos. Bajo el recuento de referencias, una referencia débil es similar a una referencia débil bajo un recolector de basura de rastreo. Es un objeto de referencia especial cuya existencia no incrementa el recuento de referencias del objeto referente. Además, una referencia débil es segura en el sentido de que cuando el objeto referente se convierte en basura, cualquier referencia débil a él caduca , en lugar de permitir que permanezca colgando, lo que significa que se convierte en un valor predecible, como una referencia nula.
Espacio de arriba (recuento de referencia)
El recuento de referencias requiere que se asigne espacio para que cada objeto almacene su recuento de referencias. El recuento puede almacenarse adyacente a la memoria del objeto o en una tabla auxiliar en algún otro lugar, pero en cualquier caso, cada objeto con recuento de referencias requiere almacenamiento adicional para su recuento de referencias. El espacio de memoria con el tamaño de un puntero sin signo se utiliza comúnmente para esta tarea, lo que significa que se deben asignar 32 o 64 bits de almacenamiento de recuento de referencias para cada objeto. En algunos sistemas, puede ser posible mitigar esta sobrecarga utilizando un puntero etiquetado para almacenar el recuento de referencias en áreas no utilizadas de la memoria del objeto. A menudo, una arquitectura en realidad no permite que los programas accedan a la gama completa de direcciones de memoria que podrían almacenarse en su tamaño de puntero nativo; se ignora una cierta cantidad de bits altos en la dirección o se requiere que sea cero. Si un objeto tiene de manera confiable un puntero en una ubicación determinada, el recuento de referencias se puede almacenar en los bits no utilizados del puntero. Por ejemplo, cada objeto en Objective-C tiene un puntero a su clase al comienzo de su memoria; En la arquitectura ARM64 que utiliza iOS 7 , se utilizan 19 bits no utilizados de este puntero de clase para almacenar el recuento de referencia del objeto. [17] [18]
Sobrecarga de velocidad (incremento/disminución)
En implementaciones ingenuas, cada asignación de una referencia y cada referencia que cae fuera del ámbito a menudo requieren modificaciones de uno o más contadores de referencia. Sin embargo, en un caso común cuando una referencia se copia de una variable de ámbito externo a una variable de ámbito interno, de modo que la duración de la variable interna está limitada por la duración de la variable externa, el incremento de la referencia se puede eliminar. La variable externa "posee" la referencia. En el lenguaje de programación C++, esta técnica se implementa y demuestra fácilmente con el uso de constreferencias. El conteo de referencias en C++ generalmente se implementa utilizando " punteros inteligentes " [19] cuyos constructores, destructores y operadores de asignación administran las referencias. Un puntero inteligente se puede pasar por referencia a una función, lo que evita la necesidad de copiar y construir un nuevo puntero inteligente (que aumentaría el conteo de referencias al ingresar a la función y lo disminuiría al salir). En cambio, la función recibe una referencia al puntero inteligente que se produce de manera económica. El método Deutsch-Bobrow de conteo de referencias aprovecha el hecho de que la mayoría de las actualizaciones del conteo de referencias se generan de hecho por referencias almacenadas en variables locales. Ignora estas referencias, solo cuenta las referencias en el montón, pero antes de que se pueda eliminar un objeto con un recuento de referencias cero, el sistema debe verificar con un escaneo de la pila y registrar que aún no existe otra referencia a él. Se puede obtener una disminución sustancial adicional en la sobrecarga de las actualizaciones de contadores mediante la fusión de actualizaciones introducida por Levanoni y Petrank . [20] [21] Considere un puntero que en un intervalo dado de la ejecución se actualiza varias veces. Primero apunta a un objeto O1, luego a un objeto O2, y así sucesivamente hasta que al final del intervalo apunta a algún objeto On. Un algoritmo de recuento de referencias normalmente ejecutaría rc(O1)--, rc(O2)++, rc(O2)--, rc(O3)++, rc(O3)--, ..., rc(On)++. Pero la mayoría de estas actualizaciones son redundantes. Para que el recuento de referencias se evalúe correctamente al final del intervalo, es suficiente realizar rc(O1)--y rc(On)++. Levanoni y Petrank midieron una eliminación de más del 99% de las actualizaciones de contadores en puntos de referencia típicos de Java.
Requiere atomicidad
Cuando se utilizan en un entorno multiproceso , estas modificaciones (incremento y decremento) pueden necesitar ser operaciones atómicas como compare-and-swap , al menos para cualquier objeto que se comparta, o potencialmente se comparta entre múltiples subprocesos. Las operaciones atómicas son costosas en un multiprocesador, y aún más costosas si tienen que ser emuladas con algoritmos de software. Es posible evitar este problema agregando recuentos de referencia por subproceso o por CPU y solo accediendo al recuento de referencia global cuando los recuentos de referencia locales se vuelven o ya no son cero (o, alternativamente, usando un árbol binario de recuentos de referencia, o incluso renunciando a la destrucción determinista a cambio de no tener un recuento de referencia global en absoluto), pero esto agrega una sobrecarga de memoria significativa y, por lo tanto, tiende a ser útil solo en casos especiales (se usa, por ejemplo, en el recuento de referencia de los módulos del kernel de Linux). La coalescencia de actualizaciones de Levanoni y Petrank [20] [21] se puede usar para eliminar todas las operaciones atómicas de la barrera de escritura. Los contadores nunca son actualizados por los subprocesos del programa durante la ejecución del programa. Solo son modificados por el recopilador, que se ejecuta como un único subproceso adicional sin sincronización. Este método se puede utilizar como un mecanismo de parada del mundo para programas paralelos y también con un recopilador de recuento de referencias concurrentes.
No en tiempo real
Las implementaciones ingenuas del conteo de referencias generalmente no brindan un comportamiento en tiempo real, porque cualquier asignación de puntero puede potencialmente hacer que una cantidad de objetos limitada solo por el tamaño total de memoria asignada se liberen de manera recursiva mientras el subproceso no puede realizar otro trabajo. Es posible evitar este problema delegando la liberación de objetos no referenciados a otros subprocesos, a costa de una sobrecarga adicional.

Análisis de escape

El análisis de escape es una técnica de tiempo de compilación que puede convertir asignaciones de montón en asignaciones de pila , reduciendo así la cantidad de recolección de basura que se debe realizar. Este análisis determina si un objeto asignado dentro de una función es accesible fuera de ella. Si se descubre que una asignación local de función es accesible para otra función o subproceso, se dice que la asignación "se escapa" y no se puede realizar en la pila. De lo contrario, el objeto se puede asignar directamente en la pila y liberar cuando la función regresa, evitando el montón y los costos de administración de memoria asociados. [22]

Disponibilidad

En términos generales, es más probable que los lenguajes de programación de alto nivel tengan la recolección de basura como una característica estándar. En algunos lenguajes que carecen de recolección de basura incorporada, se puede agregar a través de una biblioteca, como en el caso del recolector de basura Boehm para C y C++.

La mayoría de los lenguajes de programación funcional , como ML , Haskell y APL , tienen la recolección de basura incorporada. Lisp es especialmente notable por ser el primer lenguaje de programación funcional y el primer lenguaje en introducir la recolección de basura. [23]

Otros lenguajes dinámicos, como Ruby y Julia (pero no Perl  5 o PHP antes de la versión 5.3, [24] que utilizan el conteo de referencias), JavaScript y ECMAScript también tienden a utilizar GC. Los lenguajes de programación orientados a objetos como Smalltalk , RPL y Java suelen proporcionar recolección de basura integrada. Las excepciones notables son C++ y Delphi , que tienen destructores .

BÁSICO

BASIC y Logo han utilizado a menudo la recolección de basura para tipos de datos de longitud variable, como cadenas y listas, para no sobrecargar a los programadores con detalles de gestión de memoria. En el Altair 8800 , los programas con muchas variables de cadena y poco espacio de cadena podían causar largas pausas debido a la recolección de basura. [25] De manera similar, el algoritmo de recolección de basura del intérprete de Applesoft BASIC escanea repetidamente los descriptores de cadena en busca de la cadena que tenga la dirección más alta para compactarla hacia una memoria alta, lo que resulta en un mejor rendimiento [26] y pausas en cualquier momento desde unos pocos segundos hasta unos pocos minutos. [27] Un recolector de basura de reemplazo para Applesoft BASIC por Randy Wigginton identifica un grupo de cadenas en cada paso sobre el montón, lo que reduce drásticamente el tiempo de recolección. [28] BASIC.SYSTEM, lanzado con ProDOS en 1983, proporciona un recolector de basura con ventanas para BASIC que es mucho más rápido. [29]

Objetivo-C

Aunque tradicionalmente Objective-C no tenía recolección de basura, con el lanzamiento de OS X 10.5 en 2007 Apple introdujo la recolección de basura para Objective-C  2.0, utilizando un recolector de tiempo de ejecución desarrollado internamente. [30] Sin embargo, con el lanzamiento de OS X 10.8 en 2012 , la recolección de basura quedó obsoleta en favor del contador de referencia automático (ARC) de LLVM que se introdujo con OS X 10.7 . [31] Además, desde mayo de 2015 Apple incluso prohibió el uso de la recolección de basura para nuevas aplicaciones de OS X en la App Store . [32] [33] Para iOS , la recolección de basura nunca se ha introducido debido a problemas en la capacidad de respuesta y el rendimiento de la aplicación; [14] [34] en su lugar, iOS utiliza ARC. [35] [36]

Entornos limitados

La recolección de basura rara vez se utiliza en sistemas integrados o en tiempo real debido a la necesidad habitual de un control muy estricto sobre el uso de recursos limitados. Sin embargo, se han desarrollado recolectores de basura compatibles con muchos entornos limitados. [37] Microsoft .NET Micro Framework , .NET nanoFramework [38] y Java Platform, Micro Edition son plataformas de software integrado que, al igual que sus primos mayores, incluyen la recolección de basura.

Java

Los recolectores de basura disponibles en los JDK de Java incluyen:

Uso en tiempo de compilación

La recolección de basura en tiempo de compilación es una forma de análisis estático que permite reutilizar y recuperar la memoria en función de invariantes conocidas durante la compilación.

Esta forma de recolección de basura se ha estudiado en el lenguaje de programación Mercury , [40] y vio un mayor uso con la introducción del contador de referencia automático (ARC) de LLVM en el ecosistema de Apple (iOS y OS X) en 2011. [35] [36] [32]

Sistemas en tiempo real

Se han desarrollado recolectores de basura incrementales, concurrentes y en tiempo real, por ejemplo, por Henry Baker y por Henry Lieberman . [41] [42] [43]

En el algoritmo de Baker, la asignación se realiza en cualquiera de las mitades de una región de memoria. Cuando se llena a la mitad, se realiza una recolección de basura que mueve los objetos activos a la otra mitad y los objetos restantes se desasignan implícitamente. El programa en ejecución (el "mutador") tiene que comprobar que cualquier objeto al que hace referencia esté en la mitad correcta y, si no, moverlo a la otra mitad, mientras que una tarea en segundo plano busca todos los objetos. [44]

Los esquemas de recolección de basura generacional se basan en la observación empírica de que la mayoría de los objetos mueren jóvenes. En la recolección de basura generacional, se mantienen dos o más regiones de asignación (generaciones), que se mantienen separadas en función de la edad del objeto. Los objetos nuevos se crean en la generación "joven" que se recolecta regularmente y, cuando una generación está llena, los objetos a los que todavía se hace referencia desde regiones más antiguas se copian en la siguiente generación más antigua. Ocasionalmente, se realiza un análisis completo.

Algunas arquitecturas informáticas de lenguajes de alto nivel incluyen soporte de hardware para la recolección de basura en tiempo real.

La mayoría de las implementaciones de recolectores de basura en tiempo real utilizan rastreo . [ cita requerida ] Dichos recolectores de basura en tiempo real cumplen con estrictas restricciones de tiempo real cuando se utilizan con un sistema operativo en tiempo real. [45]

Véase también

Referencias

  1. ^ Abelson, Harold; Sussman, Gerald Jay; Sussman, Julie (2016). Estructura e interpretación de programas informáticos (PDF) (2.ª ed.). Cambridge, Massachusetts, EE. UU.: MIT Press . pp. 734–736.
  2. ^ "¿Qué es la recolección de basura (GC) en programación?". Almacenamiento . Consultado el 21 de junio de 2024 .
  3. ^ McCarthy, John (1960). "Funciones recursivas de expresiones simbólicas y su cálculo por máquina, Parte I". Comunicaciones de la ACM . 3 (4): 184–195. doi : 10.1145/367177.367199 . S2CID  1489409 . Consultado el 29 de mayo de 2009 .
  4. ^ "¿Qué es la recolección de basura (GC) en programación?". SearchStorage . Consultado el 17 de octubre de 2022 .
  5. ^ "Descripción general: lenguaje de programación D". dlang.org . Digital Mars . Consultado el 29 de julio de 2014 .
  6. ^ Heller, Martin (3 de febrero de 2023). "¿Qué es la recolección de basura? Gestión automatizada de memoria para sus programas". InfoWorld . Consultado el 21 de junio de 2024 .
  7. ^ "Guía para la recolección de basura en programación". freeCodeCamp.org . 2020-01-16 . Consultado el 2024-06-21 .
  8. ^ "Recolección de basura: lenguaje de programación D". dlang.org . Consultado el 17 de octubre de 2022 .
  9. ^ "Recolección de basura". rebelsky.cs.grinnell.edu . Consultado el 13 de enero de 2024 .
  10. ^ Heller, Martin (3 de febrero de 2023). "¿Qué es la recolección de basura? Gestión automatizada de memoria para sus programas". InfoWorld . Consultado el 21 de junio de 2024 .
  11. ^ Microsoft (28 de febrero de 2023). «Fundamentos de la recolección de elementos no utilizados | Microsoft Learn» . Consultado el 29 de marzo de 2023 .
  12. ^ Zorn, Benjamin (22 de enero de 1993). "El costo medido de la recolección de basura conservadora". Software: práctica y experiencia . 23 (7). Departamento de Ciencias de la Computación, Universidad de Colorado Boulder : 733–756. CiteSeerX 10.1.1.14.1816 . doi :10.1002/spe.4380230704. S2CID  16182444. 
  13. ^ Hertz, Matthew; Berger, Emery D. (2005). "Cuantificación del rendimiento de la recolección de basura frente a la gestión explícita de la memoria" (PDF) . Actas de la 20.ª Conferencia anual ACM SIGPLAN sobre programación orientada a objetos, sistemas, lenguajes y aplicaciones - OOPSLA '05 . págs. 313–326. doi :10.1145/1094811.1094836. ISBN . 1-59593031-0. S2CID  6570650. Archivado (PDF) del original el 2012-04-02 . Consultado el 2015-03-15 .
  14. ^ ab "Inicio de las herramientas para desarrolladores: sesión 300" (PDF) . WWDC 2011 . Apple, Inc. 24 de junio de 2011. Archivado desde el original (PDF) el 4 de septiembre de 2023 . Consultado el 27 de marzo de 2015 .
  15. ^ Microsoft (27 de enero de 2009). «Recolección de elementos no utilizados mediante recuento de referencias» . Consultado el 29 de marzo de 2023 .
  16. ^ "Recuento de referencias". Extensión e incrustación del intérprete de Python . 21 de febrero de 2008. Consultado el 22 de mayo de 2014 .
  17. ^ Ash, Mike. "Preguntas y respuestas del viernes 27 de septiembre de 2013: ARM64 y tú". mikeash.com . Consultado el 27 de abril de 2014 .
  18. ^ "Hamster Emporium: [objc explain]: ISA no puntero". Sealiesoftware.com. 24 de septiembre de 2013. Consultado el 27 de abril de 2014 .
  19. ^ Pibinger, Roland (3 de mayo de 2005) [17 de abril de 2005]. "RAII, objetos dinámicos y fábricas en C++".
  20. ^ ab Levanoni, Yossi; Petrank, Erez (2001). "Un recolector de basura de conteo de referencias sobre la marcha para Java". Actas de la 16.ª Conferencia ACM SIGPLAN sobre programación orientada a objetos, sistemas, lenguajes y aplicaciones . OOPSLA 2001. págs. 367–380. doi :10.1145/504282.504309.
  21. ^ ab Levanoni, Yossi; Petrank, Erez (2006). "Un recolector de basura de conteo de referencias sobre la marcha para Java". ACM Trans. Program. Lang. Syst . 28 : 31–69. CiteSeerX 10.1.1.15.9106 . doi :10.1145/1111596.1111597. S2CID  14777709. 
  22. ^ Salagnac, Guillaume; Yovine, Sergio; Garbervetsky, Diego (24 de mayo de 2005). "Análisis de escape rápido para la gestión de memoria basada en regiones". Notas electrónicas en informática teórica . 131 : 99–110. doi : 10.1016/j.entcs.2005.01.026 .
  23. ^ Chisnall, David (12 de enero de 2011). Lenguajes de programación influyentes, parte 4: Lisp.
  24. ^ "PHP: consideraciones de rendimiento". php.net . Consultado el 14 de enero de 2015 .
  25. ^ "Manual de referencia básico 4.1 del Altair 8800" (PDF) . The Vintage Technology Digital Archive . Abril de 1977. pág. 108. Archivado (PDF) desde el original el 29 de junio de 2021 . Consultado el 29 de junio de 2021 .
  26. ^ "Trabajé para acelerar la recolección de basura de cadenas en Applesoft..." Hacker News . Consultado el 29 de junio de 2021 .
  27. ^ Little, Gary B. (1985). El interior del Apple IIc. Bowie, Maryland: Brady Communications Co. pág. 82. ISBN 0-89303-564-5. Recuperado el 29 de junio de 2021 .
  28. ^ "Recolección rápida de basura". Llamada-APPLE : 40–45. Enero de 1981.
  29. ^ Worth, Don (1984). Beneath Apple Pro DOS (PDF) (edición impresa de marzo de 1985). Chatsworth, California, EE. UU.: Quality Software. págs. 2–6. ISBN 0-912985-05-4Archivado (PDF) del original el 3 de diciembre de 2008. Consultado el 29 de junio de 2021 .
  30. ^ "Descripción general de Objective-C 2.0". Archivado desde el original el 24 de julio de 2010.
  31. ^ Siracusa, John (20 de julio de 2011). "Mac OS X 10.7 Lion: la reseña de Ars Technica".
  32. ^ ab "Apple dice que los desarrolladores de aplicaciones para Mac deben realizar la transición a la gestión de memoria ARC antes de mayo". AppleInsider . 20 de febrero de 2015.
  33. ^ Cichón, Waldemar (21 de febrero de 2015). "App Store: programa exclusivo de Apple con recolección de basura". Heise.de . Consultado el 30 de marzo de 2015 .
  34. ^ Silva, Precious (18 de noviembre de 2014). «iOS 8 vs Android 5.0 Lollipop: Apple derrota a Google con eficiencia de memoria». International Business Times . Archivado desde el original el 3 de abril de 2015. Consultado el 7 de abril de 2015 .
  35. ^ ab Napier, Rob; Kumar, Mugunth (2012-11-20). Programación para iOS 6: superando los límites. John Wiley & Sons . ISBN 978-1-11844997-4. Recuperado el 30 de marzo de 2015 .
  36. ^ ab Cruz, José RC (22 de mayo de 2012). "Recuento automático de referencias en iOS". Dr. Dobbs . Archivado desde el original el 16 de mayo de 2020 . Consultado el 30 de marzo de 2015 .
  37. ^ Fu, Wei; Hauser, Carl (2005). "Un marco de trabajo de recolección de basura en tiempo real para sistemas integrados". Actas del taller de 2005 sobre software y compiladores para sistemas integrados - SCOPES '05 . págs. 20–26. doi :10.1145/1140389.1140392. ISBN 1-59593207-0.S2CID8635481  .​
  38. ^ ".NET nanoFramework".
  39. ^ Tene, Gil; Iyengar, Balaji; Wolf, Michael (2011). "C4: el colector de compactación concurrente continua" (PDF) . ISMM '11: Actas del simposio internacional sobre gestión de la memoria . doi :10.1145/1993478. ISBN 978-1-45030263-0. Archivado (PDF) del original el 9 de agosto de 2017.
  40. ^ Mazur, Nancy (mayo de 2004). Recolección de basura en tiempo de compilación para el lenguaje declarativo Mercury (PDF) (Tesis). Katholieke Universiteit Leuven . Archivado (PDF) desde el original el 27 de abril de 2014.
  41. ^ Huelsbergen, Lorenz; Winterbottom, Phil (1998). "Recolección de basura de marcado y barrido muy concurrente sin sincronización de grano fino" (PDF) . Actas del Primer Simposio Internacional sobre Gestión de Memoria - ISMM '98 . págs. 166–175. doi :10.1145/286860.286878. ISBN . 1-58113114-3. S2CID  14399427. Archivado (PDF) desde el original el 13 de mayo de 2008.
  42. ^ "Preguntas frecuentes de GC".
  43. ^ Lieberman, Henry; Hewitt, Carl (1983). "Un recolector de basura en tiempo real basado en la vida útil de los objetos". Comunicaciones de la ACM . 26 (6): 419–429. doi :10.1145/358141.358147. hdl : 1721.1/6335 . S2CID  14161480.
  44. ^ Baker, Henry G. (1978). "Procesamiento de listas en tiempo real en una computadora serial". Comunicaciones de la ACM . 21 (4): 280–294. doi :10.1145/359460.359470. hdl : 1721.1/41976 . S2CID  17661259.ver también la descripción
  45. ^ McCloskey; Bacon; Cheng; Grove (2008), Staccato: un recolector de basura compactador en tiempo real paralelo y concurrente para multiprocesadores (PDF) , archivado (PDF) desde el original el 2014-03-11

Lectura adicional

Enlaces externos