¿El recuento de referencias GC frente a GC de rastreo es una propiedad de lenguaje o una propiedad de implementación?

9

A veces escuchamos "Swift no hace GC (rastreo) clásico, usa ARC".

Pero no estoy seguro de si hay algo en la semántica de Swift que requiera un recuento de referencias. Parece que uno podría construir su propio compilador Swift y tiempo de ejecución para usar GC de rastreo.

Entonces, ¿qué es exactamente "referencia contada" sobre Swift? ¿La implementación de Apple o el lenguaje en sí? ¿Hay partes del lenguaje o de la biblioteca que soportan ARC con tanta fuerza que podemos usar esa etiqueta para el lenguaje en sí?

Ray Toal
fuente

Respuestas:

9

Swift garantiza que una vez que se suelta la última referencia a un objeto, el objeto se desinicializa y el deinitcódigo se ejecuta inmediatamente.

No es posible obtener este tipo de garantía a través de GC, al menos, no sin sacrificar el rendimiento. Los mecanismos estándar de GC solo aseguran que el deinitcódigo finalmente se ejecute, por ejemplo, en el siguiente ciclo de GC. Para una semántica precisa, necesita un recuento de referencias en alguna parte.

chi
fuente
3
Ah, entonces la presencia de deinituna palabra clave y su semántica asociada son, de hecho, las cosas que ponen el recuento de referencias directamente en el lenguaje, en lugar de la implementación, en el ámbito.
Ray Toal
2
Nada impide que un tiempo de ejecución GCed busque objetos inalcanzables cada vez que se desasigna algo. Es terriblemente ineficiente.
Raphael
@Raphael Editado para ser más preciso en ese punto.
chi
3

chi ha respondido a la pregunta específica en el cuerpo sobre swift, esta respuesta responde a la pregunta más general en el título.

¿El recuento de referencias GC frente a GC de rastreo es una propiedad de lenguaje o una propiedad de implementación?

El GC de conteo de referencias y el GC de rastreo proporcionan al programador diferentes garantías.

El recuento de referencias proporciona determinismo en la ubicación del flujo del programa donde se destruye un objeto, que puede ser importante si el objeto posee recursos escasos que deben liberarse rápidamente. Por otro lado, no puede lidiar con ciclos de referencias "fuertes".

Depende de la especificación de un idioma individual si se garantiza alguna característica y, por lo tanto, qué opciones están disponibles para una implementación compatible.

Peter Green
fuente
44
También es posible combinar refcount y GC. Luego, el lenguaje puede documentar que los objetos tienen su destructor ejecutado tan pronto como no estén referenciados (lo que implica un recuento de una forma u otra) y que los ciclos de referencia se destruirán eventualmente (lo que implica alguna forma de GC). Alternativamente, la implementación podría hacer esto mientras el lenguaje no garantiza cuándo se ejecutan los destructores (IIRC es el caso de Python y su implementación de referencia), en cuyo caso sería una propiedad de implementación.
Gilles 'SO- deja de ser malvado'
1

Puede tomar el lenguaje conocido como Swift y cambiarle el nombre a "Swift with ARC". Luego, podría crear un nuevo lenguaje llamado "Swift con GC" con exactamente la misma sintaxis, pero con menos garantías sobre cuándo se desasignan los objetos.

En Swift con ARC, una vez que el recuento de referencia es 0, el objeto irá. Con la recolección de basura, siempre que tenga una referencia débil, puede asignar esa referencia débil a una referencia fuerte para "recuperar" el objeto. (En Swift, una vez que el recuento de referencias es 0, las referencias débiles son nulas); Esa es una gran diferencia.

Y, por supuesto, Swift con ARC garantiza que matar el último recuento de referencias desasignará el objeto de inmediato. Por ejemplo, puede tener una clase FileWriter, donde no se le permite tener dos instancias que escriban en el mismo archivo al mismo tiempo. En Swift con ARC se podría decir oldWriter = nil; newWriter = FileWriter (...) y sabría que el nuevo FileWriter solo se crea después de eliminar el anterior (a menos que haya guardado otra referencia); en Swift con GC esto no funcionaría.

Otra diferencia es que en "Swift with ARC", los objetos a los que solo se hace referencia a través de fuertes ciclos de referencia, pero que en realidad no son accesibles, se garantiza que no se desasignen.

gnasher729
fuente