Ostrzeżenia dotyczące pamięci systemu operacyjnego iPhone. Co oznaczają różne poziomy?

85

Odnośnie czarnej sztuki zarządzania pamięcią na urządzeniach iPhone OS: co oznaczają różne poziomy ostrzeżeń dotyczących pamięci. Poziom 1? Poziom 2? Czy tarcza wskazuje 11?

Kontekst: Po szeroko zakrojonym okresie testów obciążeniowych pamięci - w tym po uruchomieniu aplikacji na iPada z włączoną aplikacją odtwarzacza muzyki na iPodzie, jestem skłonny zignorować losowe, ale rzadkie ostrzeżenia dotyczące pamięci, które otrzymuję. Moja aplikacja nigdy się nie zawiesza. Zawsze. Moja aplikacja jest wolna od wycieków. No cóż, ostrzeżenia memów po prostu nie wydają się mieć znaczenia.

Dzięki,
Doug

dugla
źródło

Odpowiedzi:

98

Zasadniczo ostrzeżenia oznaczają, że w urządzeniu zaczyna brakować pamięci i że „Jeśli mógłbyś zwolnić trochę pamięci, której nie używasz aktywnie, byłoby to super! ”. Jeśli zarządzanie pamięcią jest ciasne i nie masz obiektów, które praktycznie można by wyrzucić, po prostu przekaż wiadomość i zignoruj ​​ją.

Williham Totland
źródło
25
LOL "Gdybyś mógł zwolnić trochę pamięci, której aktywnie nie używasz, byłoby świetnie!" Bezcenne ;-) Pozdrawiam
dugla
15
Brzmisz jak zrzędliwy weteran tańca pamięci w stylu wack-a-mole z iPhone OS.
dugla
193

Ostrzeżenia dotyczące poziomu pamięci są rejestrowane przez SpringBoard. Jako programista aplikacji nie musisz się tym przejmować. Wystarczy odpowiedzieć -{application}didReceiveMemoryWarning.


Istnieją 4 poziomy ostrzeżeń (od 0 do 3). Są one ustawiane z obserwatora pamięci jądra i można je uzyskać za pomocą funkcji niepublicznejOSMemoryNotificationCurrentLevel() .

typedef enum {
    OSMemoryNotificationLevelAny      = -1,
    OSMemoryNotificationLevelNormal   =  0,
    OSMemoryNotificationLevelWarning  =  1,
    OSMemoryNotificationLevelUrgent   =  2,
    OSMemoryNotificationLevelCritical =  3
} OSMemoryNotificationLevel;

Sposób wyzwalania poziomów nie jest udokumentowany. SpringBoard jest skonfigurowany do wykonywania następujących czynności na każdym poziomie pamięci:

  1. Ostrzeżenie (nienormalne) - Uruchom ponownie lub opóźnij automatyczne ponowne uruchomienie nieistotnych aplikacji w tle, np. Mail.
  2. Pilne - zamknij wszystkie aplikacje działające w tle, np. Safari i iPod.
  3. Krytyczne i nie tylko - jądro przejmie kontrolę, prawdopodobnie zabije SpringBoard lub nawet uruchomi się ponownie.

Zabicie aktywnej aplikacji (jetsam) nie jest obsługiwane przez SpringBoard, ale launchd.

kennytm
źródło
Dzięki za to. To była dylemat między tobą a komikiem Willihamem w tej sprawie. Humor wygrywa. Twoje zdrowie.
dugla
Cześć, mam ten sam problem. Po ciągłym uruchomieniu aplikacji f ponad 5 razy, otrzymuję ostrzeżenie o otrzymaniu pamięci. Poziom = 1 przez 20 razy, ale aplikacja nie ulega awarii. Ale kiedy dostaję ten komunikat, Ostrzeżenie o odebraniu pamięci. Poziom = 2 moja aplikacja ulega awarii. Poziom 2 pojawia się po tym, jak Poziom 1 pojawia się prawie 20 razy. Jak mogę sprawić, by moja aplikacja nie uległa awarii. Dziękuję
srikanth rongali
1
@Kenny: Mniej pamięci oznacza, ile możemy maksymalnie wykorzystać. Ile możemy mieć żywych bajtów. W moim dzienniku awarii mam to. Darmowe strony: 371 Strony przewodowe: 12192 Strony usuwalne: 0 Największy proces: DTMobileIS Co to oznacza? Gdzie powinienem się zająć? Dziękuję Ci.
srikanth rongali
9
@srik: Lepiej zadaj nowe pytanie .
kennytm
@kennytm: czy jest to nadal możliwe z ios8? Widziałem, że funkcja jest zdefiniowana w libsystem_c.dylib. Byłoby wspaniale, gdybym mógł to wykorzystać. Dzięki
focs
12

Z OSMemoryNotification.h ,

/*
** Threshold values for notifications
*/

typedef enum {
    OSMemoryNotificationLevelAny      = -1,
    OSMemoryNotificationLevelNormal   =  0,
    OSMemoryNotificationLevelWarning  =  1,
    OSMemoryNotificationLevelUrgent   =  2,
    OSMemoryNotificationLevelCritical =  3
} OSMemoryNotificationLevel;

łącznie 5 poziomów ostrzeżeń dotyczących pamięci (-1,3).

Jeśli chodzi o opis ostrzeżenia poziomu pamięci, odpowiedź @ KennyTM jest doskonała.

Chcę dodać kilka powiązanych punktów, które mogą pomóc PM i innym.


Co należy zrobić w przypadku ostrzeżenia o poziomie pamięci?

Po otrzymaniu któregokolwiek z tych ostrzeżeń, metoda obsługi powinna zareagować, natychmiast zwalniając niepotrzebną pamięć. Na przykład, domyślnym zachowaniem klasy UIViewController jest wyczyszczenie jej widoku, jeśli ten widok nie jest obecnie widoczny; podklasy mogą uzupełniać domyślne zachowanie, usuwając dodatkowe struktury danych. Aplikacja, która utrzymuje pamięć podręczną obrazów, może zareagować, udostępniając obrazy, których aktualnie nie ma na ekranie.


Jak przestrzegać ostrzeżenia o poziomie pamięci?

Z http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/PerformanceTuning/PerformanceTuning.html

Gdy system wyśle ​​ostrzeżenie o małej ilości pamięci do Twojej aplikacji, natychmiast odpowiedz. iOS powiadamia wszystkie uruchomione aplikacje, gdy ilość wolnej pamięci spadnie poniżej bezpiecznego progu. (Nie powiadamia o zawieszonych aplikacjach). Jeśli Twoja aplikacja otrzyma to ostrzeżenie, musi zwolnić jak najwięcej pamięci. Najlepszym sposobem na to jest usunięcie silnych odniesień do pamięci podręcznych, obiektów obrazów i innych obiektów danych, które można odtworzyć później.

UIKit zapewnia kilka sposobów otrzymywania ostrzeżeń o małej ilości pamięci, w tym następujące:

  • Zaimplementuj metodę applicationDidReceiveMemoryWarning: delegata aplikacji.
  • Zastąp metodę didReceiveMemoryWarning w niestandardowej podklasie UIViewController.
  • Zarejestruj się, aby otrzymać powiadomienie UIApplicationDidReceiveMemoryWarningNotification.

Jak zmniejszyć ślad pamięciowy aplikacji?

  • Eliminacja wycieków pamięci.
  • Pliki zasobów powinny być jak najmniejsze.
  • W przypadku dużych zestawów danych użyj danych podstawowych lub SQLite.
  • Wczytuj zasoby leniwie.
  • Zbuduj swój program za pomocą opcji Thumb.

Szczegóły na http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/PerformanceTuning/PerformanceTuning.html


Jak mądrze przydzielać pamięć?

  • Zredukuj użycie obiektów automatycznie udostępnianych : dzięki automatycznemu liczeniu odwołań (ARC) lepiej jest przydzielić / zainicjować obiekty i pozwolić kompilatorowi zwolnić je za Ciebie w odpowiednim czasie. Dzieje się tak nawet w przypadku obiektów tymczasowych, które w przeszłości mogły zostać automatycznie udostępnione, aby uniemożliwić im życie poza zakresem bieżącej metody.
  • Nakładaj ograniczenia rozmiaru na zasoby : Unikaj ładowania dużego pliku zasobów, gdy wystarczy mniejszy. Zamiast używać obrazu o wysokiej rozdzielczości, użyj obrazu o odpowiednim rozmiarze dla urządzeń z systemem iOS. Jeśli musisz używać dużych plików zasobów, znajdź sposoby, aby załadować tylko tę część pliku, której potrzebujesz w danym momencie. Na przykład, zamiast ładować cały plik do pamięci, użyj funkcji mmap i munmap do mapowania części pliku do i z pamięci. Więcej informacji na temat mapowania plików do pamięci.
  • Unikaj nieograniczonych zestawów problemów : nieograniczone zestawy problemów mogą wymagać arbitralnie dużej ilości danych do obliczenia. Jeśli zestaw wymaga więcej pamięci niż jest dostępne, aplikacja może nie być w stanie ukończyć obliczeń. Twoje aplikacje powinny unikać takich zestawów, gdy tylko jest to możliwe, i pracować nad problemami ze znanymi limitami pamięci.
Md Mahbubur Rahman
źródło