Actualizar referencias no es lo único que requiere una pausa. Los algoritmos estándar comúnmente agrupados en "mark-sweep" suponen que todo el gráfico del objeto permanece inalterado mientras se marca. El manejo correcto de las modificaciones (nuevos objetos creados, referencias modificadas) requiere algoritmos alternativos bastante complicados, como el algoritmo tricolor. El término general es "recolección de basura concurrente".
Pero sí, la actualización de referencias después de la compactación también necesita una pausa. Y sí, el uso indirecto (por ejemplo, a través de una identificación de objeto persistente y una tabla hash para punteros reales) puede reducir en gran medida la pausa. Incluso podría ser posible hacer que esta parte esté libre de bloqueo si así lo desea. Seguiría siendo tan complicado acertar como cualquier concurrencia de memoria compartida de bajo nivel, pero no hay una razón fundamental por la que no funcione.
Sin embargo , tendría graves desventajas. Además de ocupar espacio adicional ( al menos dos palabras adicionales para todos los objetos), hace que cada desreferencia sea mucho más costosa. Incluso algo tan simple como obtener un atributo ahora implica una búsqueda completa de tabla hash. Yo estimaría que el golpe de rendimiento es mucho peor que para el rastreo incremental.
Su enfoque no resuelve de inmediato el problema de la recolección de basura, sino que solo lo sube un nivel. ¡Y a qué precio! Ahora, cada acceso a la memoria pasa por otra desreferencia de puntero. No podemos almacenar en caché la ubicación del resultado, ya que puede haber sido reubicada mientras tanto, siempre debemos pasar por la ID del objeto. En la mayoría de los sistemas, esta indirección no es aceptable, y se supone que detener el mundo tiene un costo total de tiempo de ejecución más bajo.
Dije que su propuesta solo mueve el problema, no lo resuelve. El problema está relacionado con la reutilización de ID de objetos. Las ID de objeto ahora son nuestro equivalente de punteros, y solo hay una cantidad finita de direcciones. Es concebible (especialmente en un sistema de 32 bits) que durante la vida útil de su programa, se hayan creado más de objetos INT_MAX, por ejemplo, en un bucle como
Si solo incrementamos la ID del objeto para cada objeto, nos quedaremos sin ID en algún momento. Por lo tanto, tenemos que averiguar qué ID todavía están en uso y cuáles son gratuitas para poder recuperarlas. ¿Suena familiar? Ahora estamos de vuelta en el punto de partida.
fuente
No hay ningún error en su línea de pensamiento, acaba de describir algo muy parecido al funcionamiento del recolector de basura Java original.
Por lo tanto, funciona, se ha probado y su ineficiencia condujo al desarrollo de sistemas de barrido y marca generacionales.
fuente
Object.getHashCode()