Czy liczenie referencji GC vs. śledzenie GC jest właściwością języka lub właściwością implementacji?

9

Czasami słyszymy: „Swift nie robi klasycznego (śledzącego) GC, używa ARC”.

Ale nie jestem pewien, czy w semantyce Swift jest coś, co wymaga zliczania referencji. Wygląda na to, że można zbudować własny kompilator i środowisko wykonawcze Swift, aby korzystać ze śledzenia GC.

Czym dokładnie jest „liczenie referencji” w Swift? Implementacja Apple'a czy sam język? Czy istnieją części języka lub biblioteki, które tak silnie wspierają ARC, że możemy użyć tej etykiety dla samego języka?

Ray Toal
źródło

Odpowiedzi:

9

Swift gwarantuje, że po upuszczeniu ostatniego odwołania do obiektu obiekt jest deinicjowany, a deinitkod jest natychmiast uruchamiany.

Uzyskanie tego rodzaju gwarancji za pośrednictwem GC nie jest możliwe - przynajmniej nie bez poświęcania wydajności. Standardowe mechanizmy GC zapewniają tylko uruchomienie deinitkodu, np. W następnym cyklu GC. Aby uzyskać precyzyjną semantykę, potrzebujesz gdzieś referencji.

chi
źródło
3
Ach, więc obecność deinitsłowa kluczowego i związana z nim semantyka to rzeczy, które umieszczają liczenie referencji w języku, a nie w sferze implementacji.
Ray Toal,
2
Nic nie stoi na przeszkodzie, aby środowisko uruchomieniowe GCed sprawdzało, czy nie ma dostępu do obiektów, gdy coś jest zwolnione. To jest po prostu okropnie nieefektywne.
Raphael
@Raphael Edytowany, aby być bardziej precyzyjnym w tym punkcie.
chi
3

chi odpowiedziała na konkretne pytanie w ciele dotyczące szybkiego, ta odpowiedź odpowiada na bardziej ogólne pytanie w tytule.

Czy liczenie referencji GC vs. śledzenie GC jest właściwością języka lub właściwością implementacji?

liczenie referencji GC i śledzenie GC zapewniają programiście różne restauracje.

Zliczanie referencji zapewnia determinizm w lokalizacji w przepływie programu, w którym obiekt jest niszczony, co może być ważne, jeśli obiekt posiada ograniczone zasoby, które należy szybko uwolnić. Z drugiej strony nie radzi sobie z cyklami „silnych” referencji.

To zależy od specyfikacji konkretnego języka, co jeśli dowolne cechy są restauracjami, a zatem jakie opcje są dostępne dla zgodnego wdrożenia.

Peter Green
źródło
4
Można również łączyć refcount i GC. Następnie język może udokumentować, że obiekty mają uruchomione destruktory, gdy tylko nie zostaną odwołane (co oznacza ponowne przeliczenie w takiej czy innej formie) i że cykle referencyjne zostaną ostatecznie zniszczone (sugerując jakąś formę GC). Alternatywnie implementacja mogłaby to zrobić, podczas gdy język nie gwarantuje uruchomienia destruktorów (IIRC dotyczy Pythona i implementacji referencyjnej), w którym to przypadku byłaby to właściwość implementacji.
Gilles „SO- przestań być zły”
1

Możesz zmienić język na Swift i zmienić jego nazwę na „Swift with ARC”. Następnie możesz utworzyć nowy język o nazwie „Swift with GC” z dokładnie taką samą składnią, ale z mniejszą gwarancją, kiedy obiekty zostaną zwolnione.

W Swift z ARC, gdy liczba odniesień wyniesie 0, obiekt pójdzie. W przypadku wyrzucania elementów bezużytecznych, dopóki masz słabe odniesienie, możesz przypisać to słabe odniesienie do silnego odniesienia, aby „odzyskać” obiekt. (W Swift, gdy liczba referencji wynosi 0, słabe referencje są zerowe); to główna różnica.

I oczywiście Swift z ARC gwarantuje, że zabicie ostatniego licznika referencyjnego natychmiast zwolni obiekt. Na przykład możesz mieć klasę FileWriter, w której nie mogą istnieć dwie instancje zapisujące do tego samego pliku w tym samym czasie. W Swift z ARC można powiedzieć oldWriter = zero; newWriter = FileWriter (...) i będziesz wiedział, że nowy FileWriter jest tworzony dopiero po usunięciu starego (chyba że zachowałeś inne odniesienie); w Swift z GC to nie działałoby.

Inna różnica polega na tym, że w „Swift with ARC” obiekty, do których odwołuje się tylko silny cykl odniesienia, ale których nie można osiągnąć , są gwarantowane, że nie zostaną zwolnione.

gnasher729
źródło