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.
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.
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.
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 😉
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.
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ć.
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…
@radex – podobnie są zdefiniowane w Javie ;), polecam przeczytać RFC
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().