< >  wszystkie blogi

salival's absurdlog

Potwornie absurdalny blog

Pamięciożerny FireFox - anatomia problemu

17 marzec 2008 ·

Poniekąd notkę tą zainspirował sam Joe swoją notką na temat przeglądarek: O tu.



1. Kto winny?


FireFox należy do najpopularniejszych przeglądarek internetowych, jednak nadal wielu użytkowników narzeka na fakt zużywania ogromnej ilości pamięci oraz spowolnienie działania wraz z tym. Ma to swoje uzasadnienie i nie jest to jednoznacznie wina twórców FireFox. Winne sytuacji są dwie strony:

- deweloperzy FF,
- twórcy pluginów.

Zabrało mi trochę czasu zapoznanie się z anatomią FireFox, a szczególnie z anatomią samego silnika Gecko. Jest to olbrzymia maszyna i trudno zgłębić jej wszelkie aspekty. Sam jednak skupiłem się na zarządzaniu pamięcią oraz pluginach, a szczególnie jednym - pluginie do odtwarzania flash'y.

2. Zarządzanie pamięcią


Generalnie FF zarządza pamięcia w podobny sposób jak każda inna aplikacja. Alokuje minimalną ilość pamięci ( zależną od tego ile mamy całej w komputerze ) po czym po przekroczeniu zaalokowanego obszaru dodaje koleje tyle zwiększając tzw. heap. Zwiększenie ilości zaalokowanej pamięci wiąże się z realokacją, czyli przemieszczeniem wszystkiego co zaalokowane w inne miejsce pamięci + defragmentacja ( jest to proces polegający dokładnie na tym samym, co w przypadku dysku ). Więc nic zaskakującego w tym nie ma. Działa tak Opera, Safari i wszystko inne. Skąd więc pojawia się problem wycieków pamięci, jeżeli Gecko doskonale "wie" ile i gdzie jest jej zaalokowane, co więcej, zaalokowany jest tylko jeden duży obszar. Wystarczy wywołać jedną funkcję by wszystko zdealokować i już. Większość aplikacji ma również ustalony tzw. maximum heap, czyli ilość zaalokowanej pamięci, przy której pojawia się stosowne ostrzeżenie i aplikacja stara się zdeallokować jej tyle ile tylko możliwe. Nazywa się to memory flush i do tego wrócimy za chwilę ( tu leży właśnie wina twórców FF, ale o tym później ).

Odpowiedź jest jedna i dosyć prosta. Poważne źródło problemu leży w tzw. thirdparty modules, czyli w częściach FF, nad którymi silnik Gecko nie ma kontroli ( lub ma, ale niecałkowitą ). Do takich należą często właśnie pluginy, których twórcy zapominają o tym, że piszą dla FF portując niemal w całości kod takich samych aplikacji w wersji standalone. Dla przykładu poruszę temat najbardziej pamięciożernego pluginu - Flash Player. Jak Joe wspomniał, po kilku wyświetlonych filmikach zużycie pamięci drastycznie wzrasta i nie ma w tym nic dziwnego.

3. Problem w praktyce



Przeanalizujmy dokładnie powyższy przypadek:

- Załóżmy, że FF ma zaalokowany minimalny heap na 32MB ( o ile się nie mylę, to właśnie tyle ma przy 2GB pamięci RAM ), po dotychczasowym używaniu przeglądarki mamy zajęte około 28MB, czyli zostają 4MB heap'u wolne.

- Odpalamy filmik z YouTube, uruchamia się plugin, alokuje pamięć, 4MB to za mało, FF zwiększa heap o kolejne 32MB. Mamy już zajęte więc 64MB przez heap, a dla zasobów wolnej pamięci pozostają wspomniane 4MB + nowe 32MB czyli 36MB. Z tym znów można działać. Realokacja pamięci przebiegła w tej sytuacji szybko, niemal niezauważalnie.

- Filmik ładuje się, player alokuje pamięć dla bufora i... i tu jest własnie przysłowiowy pies pogrzebany. Player nie alokuje pamięci funkcjami dostarczonymi przez Gecko, są to kolejno:

void *NPN_MemAlloc (uint32 size);

oraz:

void *NPN_MemFree (uint32 size);

W zamian z kolei używa funkcji takich, jakie wykorzystuje ten sam player w wersji standalone. Pamięć bufora sumuje się z heap, więc FF zajmuje 64MB + to co flashplayer zaalokował "na lewo". FlashPlayer działa, robi swoje, olewa funkcje interfejsu Gecko i.. kończymy zabawę. Gecko wtedy automatycznie wywołuje funkcje "czyszczenia" po pluginie, a w tej funkcji usuwa się wszystko co zostało zaalokowane przez plugin "legalnie". Programiści zapominają wtedy często, że coś jeszcze trzeba usunąć ;) Co się dało zdealokować, to się dało, co zostało to zostało.

- Uruchamiamy kolejne filmiki, sytuacja analogiczna, po 10 filmikach mamy już nie 64, ale powiedzmy 256. Przynajmniej teoretycznie, bo to czego nie zwolnił plugin zaowocuje nam ponad 300MB zajętymi.

Odstąpienie od wykorzystania silnika Gecko jako mechanizmu zarządzania pamięcią jest największym "grzechem" twórców pluginów. Dlatego sam preferuję po prostu używać flashblocker'ów i decydować, które flashę chcę wyświetlić ;)

4. Zwalnianie pamięci i niekonsekwencja



To jednak nie koniec. Wrócę do wspomnianego wcześniej memory flush czyli defragmentacja i zdealokowanie pamięci-nadwyżki. W tym celu stworzono specjalną funkcję:

uint32 NPN_MemFlush(uint32 size);

I oczywiście twórcy pluginów bardzo chętnie jej używają. Zapominają jednak, że działa ona tylko.. na OS X ;)

5. Podsumowanie


Podsumowując, cały problem leży w:

- zbyt dużej swobodzie danej programistom pluginów w kwestii zarządzania pamięcią,

- brak konsekwencji ze strony programistów FF w kwestii implementacji managera pamięci dla różnych systemów

- bark tzw. garbage collectora czyli prostego systemu starającego się zwrócić najwięcej pamięci jak to tylko możliwe poprzez zdealokowanie wszystkiego, co uznane jest za "niepotrzebne". Funkcja NPN_MemFlush(), ma pełnić taką funkcję, ale co z tego, skoro działa ona tylko na OSX. Dodam, że na OSX praktycznie nie ma problemu z wyciekami pamięci z tego powodu.

6. Co dalej czyli FireFox 3.0


Joe również wspomniał, że ma nadzieję, że sytuacja się poprawi wraz z nadjeściem FF3. Niekoniecznie, 50% winy leży nadal w twórcach pluginów. Obecnie można przekompilować FF3 i przetestować samemu. Testowałem jakiś czas temu bardzo "pierwszą" wersję skompilowaną pod Linux oraz niedawno wersję pod Windows. Problem z flashami pozostaje nadal nierozwiązany i przypuszczam, że nowy FF może nie przynieść rozwiązania tego problemu, chyba że:

- ograniczą swobodę programistów w kwestii zarządzania pamięcią,
- uniemożliwią uruchamianie pluginów z FF2 wymuszając na twórcach rekompilację istniejących z uwzględnieniem nowych reguł - czyli żadnej samowolki.

Jak na razie nic takiego miejsca nie ma.

Jest jeszcze jeden aspekt problemów z firefox'em - ładowanie grafiki, dekompresja jej i trzymanie w pamięci "tak na wszelki wypadek", ale nie wspominam o tym, bo wygląda, że problem w FF3 jest rozwiązany.

Starałem się w miare zrozumiale opisać temat ;)


 

1 komentarz
joemonster
joemonster -   |  4 lata i 2 miesiące temu  |  
No nie dajesz zbyt wiele nadziei dla fanów FF, choć teraz z tą wiedzą będzie nam trochę lżej :)
 

Dobra, dobra. Chwila. Chcesz oceniać i komentować pliki?

Zaloguj się lub zarejestruj jako nieustraszony bojownik walczący z powagą

Napędzana humorem dzięki Joe Monsterowi