Nowości z php.internals – słabe referencje do obiektów

Od jakiegoś czasu w zbiorze propozycji nowych „ficzerów” do PHP znajduje się RFC pod tajemniczą nazwą „Weak references”. W czym właściwie jest rzecz i czym są owe „słabe referencje” ? Cały pomysł został zaczerpnięty przez autorów z Javy, C# i Pythona. Rozwiązuje on problem związany ze zwalnianiem pamięci i garbage collectorem. Problem, kiedy mamy zbyt dużo referencji do jakiś obiektów i nie zostają one nigdy zebrane przez GC. Słaba referencja, w przeciwieństwie do standardowej „mocnej” nie powoduje zwiększenia licznika ilości referencji, po którym GC rozpoznaje, czy może już dany obiekt usunąć z pamięci.

Kiedy się to może przydać ? Prosty przykład, stosujemy wzorzec obserwator. Obserwowany obiekt zwany też podmiotem rejestruje subskrybentów, których będzie powiadamiał o zmianie swojego stanu. Takich subskrybentów może być bardzo wielu. Może się zdarzyć, że któryś subskrybent mógłby już zostać usunięty z pamięci przez GC, gdyby nie ta ostatnia referencja, którą trzyma podmiot. W efekcie przy wielu obiektach subskrybentów, tracimy niepotrzebnie pamięć. Rozwiązaniem jest zastosowanie słabej referencji. Dzięki niej, w momencie, gdy wszystkie inne zewnętrzne referencje do danego subskrybenta wygasną zostanie on od razu zebrany przez GC.

Implementacja zaproponowana w RFC postuluje stworzenie klasy SplWeakRef. Jej zastosowanie będzie wymagało tylko przekazania do jej konstruktora zmiennej do obiektu, który ma być słabą referencją.

class Foo {}

$foo = new Foo; //reference count 1
$bar = $foo; //reference count 2

$slabaReferencja = new SplWeakRef($foo); //reference count 2

Jestem ciekaw co sądzicie o tej propozycji ? Osobiście wydaje mi się dość ciekawa, natomiast chyba pole zastosowań jest naprawdę bardzo małe, a potencjalnie może być ten „ficzer” bardzo niebezpieczny w rękach początkujących programistów. Osobiście zamiast tego mechanizmu, wolałbym możliwość deklarowania klas tak, by ich obiekty były przekazywane przez kopię, tak jak typy proste. Moim zdaniem dużo bezpieczniejsze rozwiązanie a efekt podobny.

  1. wookieb pisze:

    Raczej kopia byłaby znacznie bardziej problematyczna. Aktualnie rozwiązanie jest moim zdaniem lepsze a początkujący nawet nie znają SPL-a (sprawdzone) więc nie ma szans by tego użyli.

  2. No właśnie kopia nie, bo przy przekazaniu można zwolnić poprzednią referencję, albo zastosować copy on write co jest już zaimplementowane w PHP dla typów prostych. Zresztą to jest właśnie wielka zaleta ValueObjects – jeżeli masz coś niemodyfikowalnego (w sensie stanu) i przekazywanego przez kopie, łatwo to może kompilator/interpreter zoptymalizować pod kątem zużycia pamięci.

  3. DeyV pisze:

    w systemach pracujących na dużej ilości obiektów ze sobą powiązanych – często w obie strony – takie rozwiązanie byłoby świetnym lekarstwem na problemy z pamięcią.

    Od dawna o czymś takim śnimy w firmie po nocach 😉

  4. Quadina pisze:

    Ciekawa propozycja, aż się boję kiedy będą pierwsze implementacje kodu z tym.

    @Deyv: Kto śni ten śpi, jednak nie każdemu to w firmie dane.

  5. Zyx pisze:

    Jak to będzie zrealizowane jako klasa SPL-a, to gwarantuję, że żaden początkujący nawet do tego nie zajrzy :). Patrz: wszystkie inne klasy SPL-a. Dziwię się, że właśnie ta funkcjonalność wywołała takie obawy.

    Ja jestem za, bowiem słabe referencje to przydatna rzecz. Choć każde żądanie HTTP w PHP budowane jest od nowa, to umiejętne ich wykorzystanie może zmniejszyć zapotrzebowanie na pamięć przy bardziej skomplikowanych operacjach i ułatwić sprzątanie po nim, jeśli skrypt ma coś jeszcze później liczyć.

  6. radex pisze:

    IMHO będzie _bardzo_ niszowy. Niewiele osób piszących w PHP ma pojęcie, a co dopiero zainteresowanie co do zarządzania pamięcią. For the rest of us, ficzer się przyda.

    Tylko sposób definiowania nieelegancki…

  7. @radex – podobnie są zdefiniowane w Javie ;), polecam przeczytać RFC

  8. radex pisze:

    Hmm… Rzeczywiście…

    Szczerze mówiąc, moje jedyne doświadczenie w tym temacie jest związane z Objective C, gdzie słabe referencje są definiowane za pomocą modyfikatora __weak. Nie jest to idealnie eleganckie, ale jak na moje bardziej niż new SplWeakRef().

  1. There are no trackbacks for this post yet.

Leave a Reply

Informuj mnie o odpowiedziach poprzez e-mail. Możesz również subskrybować wpis bez zostawiania komentarza.