Ist die Referenzzählung von GC gegenüber der Verfolgung von GC eine Spracheigenschaft oder eine Implementierungseigenschaft?

9

Wir hören manchmal "Swift macht keine klassische (Tracing-) GC, es verwendet ARC."

Ich bin mir jedoch nicht sicher, ob die Swift-Semantik irgendetwas enthält, das eine Referenzzählung erfordert. Es scheint, dass man seinen eigenen Swift-Compiler und seine eigene Laufzeit erstellen könnte, um Tracing-GC zu verwenden.

Was genau ist an Swift "referenzgezählt"? Apples Implementierung oder die Sprache selbst? Gibt es Teile der Sprache oder der Bibliothek, die ARC so stark unterstützen, dass wir dieses Label für die Sprache selbst verwenden können?

Ray Toal
quelle

Antworten:

9

Swift garantiert, dass das Objekt nach dem Löschen des letzten Verweises auf ein Objekt deinitialisiert und der deinitCode sofort ausgeführt wird.

Eine solche Garantie durch GC zu erhalten, ist nicht möglich - zumindest nicht ohne Leistungseinbußen. Standard-GC-Mechanismen stellen nur sicher, dass der deinitCode schließlich ausgeführt wird, z. B. beim nächsten GC-Zyklus. Für eine genaue Semantik benötigen Sie irgendwo einen Referenzzähler.

Chi
quelle
3
Ah, das Vorhandensein deiniteines Schlüsselworts und die damit verbundene Semantik sind in der Tat die Dinge, die die Referenzzählung genau in den Sprach- und nicht in den Implementierungsbereich stellen.
Ray Toal
2
Nichts hindert eine GCed-Laufzeit daran, nach nicht erreichbaren Objekten zu suchen, wenn etwas freigegeben wird. Es ist einfach schrecklich ineffizient.
Raphael
@ Raphael Bearbeitet, um in diesem Punkt genauer zu sein.
Chi
3

Chi hat die spezifische Frage im Körper über schnell beantwortet, diese Antwort beantwortet die allgemeinere Frage im Titel.

Ist die Referenzzählung von GC gegenüber der Verfolgung von GC eine Spracheigenschaft oder eine Implementierungseigenschaft?

Referenzzähl-GC und Tracing-GC bieten dem Programmierer verschiedene Garantien.

Die Referenzzählung sorgt für Determinismus an der Stelle im Programmablauf, an der ein Objekt zerstört wird. Dies kann wichtig sein, wenn das Objekt knappe Ressourcen besitzt, die schnell freigegeben werden müssen. Andererseits kann es nicht mit Zyklen "starker" Referenzen umgehen.

Es liegt an der Spezifikation einer einzelnen Sprache, welche Merkmale garantiert werden und welche Auswahlmöglichkeiten für eine konforme Implementierung zur Verfügung stehen.

Peter Green
quelle
4
Es ist auch möglich, Refcount und GC zu kombinieren. Dann kann die Sprache dokumentieren, dass Objekte ihren Destruktor ausführen lassen, sobald sie nicht mehr referenziert sind (was bedeutet, dass in der einen oder anderen Form erneut gezählt wird) und dass Referenzzyklen schließlich zerstört werden (was eine Form von GC impliziert). Alternativ könnte die Implementierung dies tun, während die Sprache nicht garantiert, wann Destruktoren ausgeführt werden (IIRC ist der Fall von Python und seiner Referenzimplementierung). In diesem Fall wäre es eine Implementierungseigenschaft.
Gilles 'SO - hör auf böse zu sein'
1

Sie können die als Swift bekannte Sprache in "Swift with ARC" umbenennen. Sie können dann eine neue Sprache mit dem Namen "Swift with GC" mit genau derselben Syntax erstellen, jedoch mit weniger Garantien, wann Objekte freigegeben werden.

In Swift mit ARC wird das Objekt gelöscht, sobald der Referenzzähler 0 ist. Bei der Speicherbereinigung können Sie, solange Sie eine schwache Referenz haben, diese schwache Referenz einer starken Referenz zuweisen, um das Objekt "wiederherzustellen". (In Swift sind schwache Referenzen gleich Null, sobald der Referenzzähler 0 ist.) Das ist ein großer Unterschied.

Und natürlich garantiert Swift with ARC, dass durch das Beenden des letzten Referenzzählers das Objekt sofort freigegeben wird. Beispielsweise haben Sie möglicherweise eine FileWriter-Klasse, in der nicht zwei Instanzen gleichzeitig in dieselbe Datei schreiben dürfen. In Swift mit ARC könnte man oldWriter = nil sagen; newWriter = FileWriter (...) und Sie würden wissen, dass der neue FileWriter erst erstellt wird, nachdem der alte gelöscht wurde (es sei denn, Sie haben eine andere Referenz beibehalten); In Swift mit GC würde dies nicht funktionieren.

Ein weiterer Unterschied besteht darin, dass in "Swift with ARC" Objekte, auf die nur durch starke Referenzzyklen verwiesen wird, die jedoch nicht tatsächlich erreichbar sind, garantiert nicht freigegeben werden.

gnasher729
quelle