Dlaczego wyciekła pamięć wydaje się malloceded do kernel_task i dlaczego OS X nie może więc jej wyrzucać

11

Wcześniej mówiono mi, że oznaką przecieku pamięci w niektórych aplikacjach jest kernel_taskduży ślad pamięci, zwykle rzędu gigabajtów. Gdyby nieużywanie kextpowodowało takie użycie pamięci, spodziewalibyśmy się rozbieżności między przydzieloną pamięcią a oczekiwanymi do przydzielenia, tj.

diff <(kextstat|tr -s ' ' | cut -d ' ' -f 5) <(kextstat| tr -s ' ' | cut -d ' ' -f 6) 

zwróci coś innego niż słowa „Przewodowy” i „Nazwa”.

Podczas pisania mojej pracy zauważyłem, że zmiana pliku pdf, gdy jest on otwarty w Podglądzie, często powoduje złe rzeczy: czasami zużycie pamięci kernel_taskmoże wzrosnąć do około ośmiu gigabajtów lub więcej. Jeśli zabiję podgląd, natychmiast wraca do normy . Więc oczywiście coś jest nie tak - i w tych warunkach Preview wycieka pamięć.

Więc moje pytanie brzmi: czy ja wiem, że proces wyciekł barana poprzez nagły i nieoczekiwany wzrost śladu kernel_task, dlaczego nie mogą OS X , że coś poszło nie tak. Jeśli zabicie Preview przywraca moją brakującą malloc()pamięć, dlaczego Darwin nie robi dla mnie automatycznego usuwania śmieci?

Czy mam fundamentalne nieporozumienie dotyczące sposobu zarządzania pamięcią?

EDYCJA: (15/9/15)

Oto demonstracja tego, o czym mówię. Przede wszystkim zauważam wysokie zużycie pamięci przez kernel_task(uwaga: Podgląd jest otwarty, tylko widoczny na dole Monitora aktywności, używając 333 MiB pamięci RAM):

Wysokie użycie pamięci jądra

Po pomocnych uwagach Ashleya poniżej dowiedzmy się, ile zużywa każdy kext:

$ kextstat | awk 'NR==1{ printf "%10s %s\n", $5, $6; } NR!=1{ printf "%10d %s\n", $5, $6; }' | sort -n

...
...
...
   1249280 com.apple.driver.DspFuncLib
   1769472 com.apple.nvidia.driver.NVDAGK100Hal
   2629632 com.apple.nvidia.driver.NVDAResman
   6184960 com.apple.driver.AirPort.Brcm4360
$

A więc niezbyt duża kwota. Moja maszyna ma zarówno dyskretne, jak i zintegrowane procesory graficzne; ich sterowniki używają tylko kilku MiB przewodowego pamięci RAM. Na moim przeczuciu zabijmy Preview i zobaczmy, co stanie się z odciskiem pamięci kernel_task:

Podgląd zabijania pomaga

Podgląd zniknął, a ślad pamięci jądra dramatycznie spadł. Nadal nie ma dowodów na zmianę użycia kext: wynik powyższego polecenia pozostaje niezmieniony.

Edycja : Błąd zgłoszony jako nr 22701036. Nadal czekam na odpowiedź od Apple. Nie ma nic szczególnie interesującego, jeśli obejrzysz proces w ActivityMonitor, ale może coś mi brakuje.

Landak
źródło
Mam wątpliwości co do dwóch rzeczy - czy możesz to wyjaśnić? 1) Myślę, że twoje diffpolecenie porównuje kolumny Sizei Wiredz danych kextstatwyjściowych. Zgadzam się, że Sizejest to „przydzielona pamięć”, ale nie sądzę, że Wired„oczekuje się, że zostanie przydzielona” ( man kextstatopisuje to jako „Liczbę przewodowych bajtów pamięci jądra zajmowanych przez kext”). 2) Czy widzisz rozbieżność pomiędzy Sizei Wiredkiedy masz problem z podglądem?
Ashley,
1) Masz rację - porównuję elementy w polu Rozmiar i Przewodowe z kextstat. Rozumiem, że jeśli kext przecieka, wówczas przydzielone bajty i te, o których jądro wie, że przydzielone, będą różne. W tym przypadku umieściłem to, aby pokazać, że nie mam nieszczelnego kext - więc 2) nie dzieje się tak, gdy Preview zjada ram. Zamiast tego kernel_taskdużo rośnie. Spróbuję odtworzyć ten problem i zrobić zdjęcie :-).
Landak
Dzięki! Chwileczkę: piszę odpowiedź, która może pomóc.
Ashley,

Odpowiedzi:

6

Rdzeń OS X nie jest śmieci zebrane; Libkern C ++ Runtime w IOKit wymaga od programistów zarządzania własną pamięcią.

Zarządzanie pamięcią Mac

Od Jak działa zarządzanie pamięcią w Mac OS X?

Apple dokumentuje najniższe poziomy jądra Macha i podsystemu pamięci wirtualnej dość dobrze w Internecie jako część dokumentacji dla deweloperów.

Ponieważ to jądro zostało opracowane przez Carnegie Mellon University , można z łatwością znaleźć dziesiątki artykułów opisujących je.

Innych źródeł

Zbieranie śmieci

Śmieci istnieje na poziomie użytkownika lub aplikacji. Nawet na tej warstwie wyrzucanie elementów bezużytecznych pomaga tylko wtedy, gdy aplikacja zwolniła wszystkie roszczenia do pamięci. Zależność cykliczna może pokonać zbieranie śmieci. Samo wywóz śmieci jest ewoluującym obszarem badań i trudno go naprawić .

Zgłoś błędy i wycieki pamięci

Błędy w systemie OS X spowodują wyciek pamięci. Biorąc pod uwagę rozmiar podstawy kodu, jest to prawie pewne.

Powtarzalne błędy należy zgłaszać bezpośrednio do Apple . Każdy raport o błędzie pomaga, a być może twój przykład pomoże inżynierom Apple ustalić przyczynę.

Graham Miln
źródło
Jest to rozczarowujące, ale niewątpliwie poprawne. Zgłosiłem błąd do Apple'a - po prostu uważam to za irytujące!
Landak
2
Czy możesz udostępnić numer błędu jako edycję swojego pytania. Inni, którzy uznają twoje pytanie za pomocne, mogą następnie zduplikować błędy, odnotowując oryginał. Stos powiązanych błędów pomoże uzasadnić więcej czasu na inżynierię.
Graham Miln,
4

Oto moje przypuszczenie, zakładając, że Twój komputer Mac ma zintegrowany procesor graficzny (np. Intel Iris Graphics).

Gdy Twoja praca dyplomowa jest otwarta w podglądzie, pamięć karty graficznej służy do przechowywania obrazu („tekstury”) okna podglądu, a być może również niektórych stron poza ekranem, ale dekodowanych z pracy dyplomowej.

Dzięki zintegrowanej karcie graficznej pamięć wideo jest (częściowo?) Zlokalizowana w systemowej pamięci RAM, która jest współdzielona przez procesor i kartę graficzną. W przypadku niektórych zintegrowanych kart graficznych ilość używanej pamięci RAM jest przydzielana dynamicznie (patrz Apple HT204349 ).

Domyślam się, że sporadycznie widzisz błąd w sterowniku karty graficznej i / lub Preview, który nie zwalnia poprawnie pamięci systemowej, gdy Preview przeładowuje twoją pracę w formacie PDF. (Jednak ten błąd jest minimalizowany przez OS X / sterownik poprawnie zwalnia pamięć po zamknięciu Preview).

Możesz spróbować spojrzeć na wynik kextstati sprawdzić, czy liczby w Sizekolumnie wzrosną, gdy wystąpi problem. Moja teoria jest taka, że ​​wspomniany wzrost o 8 GB będzie spowodowany sterownikiem karty graficznej.

Następujące polecenie (z komentarzem na temat tej odpowiedzi związane i ciekawy ) sortuje wyjście kextstataby łatwiej zobaczyć, które kext korzysta najwięcej pamięci (chociaż Uwaga Ta sortuje przez Wiredkolumnę ... jest podobna, prostsze zaklęcie w ten odpowiedz, jeśli chcesz to poprawić).

kextstat | awk 'NR==1{ printf "%10s %s\n", $5, $6; } NR!=1{ printf "%10d %s\n", $5, $6; }' | sort -n
Ashley
źródło
Zgaduję - i bardzo dziękuję za użyteczne, posortowane wyjście kextstat. Jednak nadal nie wygląda na to, co się właściwie dzieje: podczas pożerania podglądu ślad pamięci com.apple.nvidia.driver.*pozostał niezmieniony. Zredagowałem moje pytanie, aby to odzwierciedlić.
Landak