2008-12-12 12 views
34

Pracuję nad grą 2D dla iPhone'a przy użyciu OpenGL ES i ciągle uderzam w limit pamięci 24 MB - moja aplikacja zawiesza się z kodem błędu 101. Bardzo się starałem, aby znaleźć miejsce, w którym znajduje się pamięć , ale liczby w instrumencie są wciąż dużo większe, niż się spodziewałem.Zrozumienie zużycia pamięci na iPhonie

Uruchomiłem aplikację za pomocą monitorów pamięci, Object Alloc, Leaks i OpenGL ES instruments. Po załadowaniu aplikacji wolna pamięć fizyczna spada z 37 MB do 23 MB, Object Alloc ustawia około 7 MB, przecieki pokazują dwa lub trzy przecieki o wielkości kilku bajtów, rozmiar obiektu Gart wynosi około 5 MB, a Monitor Pamięci mówi Aplikacja zajmuje około 14 MB pamięci rzeczywistej. Jestem zdumiony, skąd się wzięła pamięć - kiedy przekopuję się na Przydziały Obiektów, większość pamięci znajduje się w teksturach, dokładnie tak, jak bym się spodziewał. Ale zarówno mój własny licznik alokacji tekstury, jak i Rozmiar Obiektu Gart zgadzają się, że tekstury powinny zająć około 5 MB.

Nie jestem świadomy przydzielenia niczego innego, o czym warto wspomnieć, a przedmiotowa umowa jest zgodna. Gdzie idzie pamięć? (Byłbym zadowolony dostarczyć więcej szczegółów, jeśli to nie wystarcza.)


Aktualizacja: Naprawdę starał się znaleźć, gdzie mogę przeznaczyć tak dużo pamięci, ale bez rezultatu. To, co mnie wkurza, to różnica między przydziałem obiektów (~ 7 MB) a rzeczywistym wykorzystaniem pamięci, jak pokazuje to Monitor Pamięci (~ 14 MB). Nawet jeśli byłyby olbrzymie przecieki lub olbrzymie ilości pamięci, o których zapominam, powinien nadal pokazywać się w Object Allocations, nieprawdaż?

Próbowałem już usualsuspects, czyli. UIImage z buforowaniem, ale to nie pomogło. Czy istnieje sposób śledzenia użycia pamięci "stylu debuggera", linia po linii, obserwując wpływ każdej z instrukcji na wykorzystanie pamięci?


co znalazłem do tej pory:

  1. Naprawdę am użyciu tego dużo pamięci. Nie jest łatwo zmierzyć rzeczywiste zużycie pamięci, ale po długim liczeniu uważam, że zużycie pamięci jest naprawdę wysokie. Moja wina.

  2. Nie znalazłem łatwego sposobu pomiaru używanej pamięci. Numery Monitora Pamięci są dokładne (są to liczby, które naprawdę mają znaczenie), ale Monitor Pamięci nie może powiedzieć, gdzie dokładnie znajduje się pamięć. Narzędzie Object Alloc jest prawie bezużyteczne do śledzenia rzeczywistego wykorzystania pamięci. Kiedy tworzę teksturę, przydzielony licznik pamięci idzie na jakiś czas (odczytuje teksturę do pamięci), a następnie upuszcza (przekazując dane tekstury do OpenGL, uwalniając). Jest to OK, ale nie zawsze tak się dzieje - czasami użycie pamięci pozostaje wysokie nawet po przekazaniu tekstury do OpenGL i zwolnieniu z "mojej" pamięci. Oznacza to, że całkowita ilość przydzielonej pamięci, jak pokazano w narzędziu Alloc obiektu, jest mniejsza niż rzeczywiste całkowite zużycie pamięci, ale większa niż rzeczywiste zużycie minus tekstury (real – textures < object alloc < real). Domyśl.

  3. Źle odczytałem Przewodnik programowania. Limit pamięci 24 MB dotyczy tekstur i powierzchni, a nie całej aplikacji. Rzeczywista czerwona linia leży nieco dalej, ale nie mogłem znaleźć żadnych twardych liczb. Konsensus jest taki, że 25-30 MB to pułap.

  4. Gdy system zaprze się pamięci, rozpoczyna wysyłanie ostrzeżenia o pamięci.Nie mam prawie nic do uwolnienia, ale inne aplikacje zwalniają pamięć z powrotem do systemu, zwłaszcza Safari (który wydaje się buforować strony internetowe). Kiedy wolna pamięć, jak pokazano w Monitorze pamięci, zera, system zaczyna zabijać.

Musiałem ugryźć kulę i przepisać niektóre fragmenty kodu, aby zwiększyć efektywność pamięci, ale prawdopodobnie nadal ją pcham. Gdybym miał zaprojektować kolejną grę, z pewnością pomyślałem o przywoływaniu zasobów. W obecnej grze jest to dość trudne, ponieważ rzecz jest w ruchu przez cały czas, a ładowanie tekstur przeszkadza, nawet jeśli jest wykonywane w innym wątku. Byłbym bardzo zainteresowany tym, jak inni ludzie rozwiązują ten problem.

Należy pamiętać, że są to tylko moje opinie, które nie muszą być zbyt dokładne. Jeśli dowiem się czegoś więcej na ten temat, zaktualizuję pytanie. Pozostawiam pytanie otwarte na wypadek, gdyby ktoś, kto rozumie problem, zechciałby odpowiedzieć, ponieważ wszystkie te są bardziej możliwe do obejścia i odgadnięcia niż cokolwiek innego.

Odpowiedz

11

ja wątpię to jest błąd w Instruments.

Najpierw przeczytaj ten blog post by Jeff Lamarche about openGL textures:

  • posiada prosty przykład, jak załadować tekstur bez przecieków powodujących
  • daje zrozumienie jak „małych” obrazów, uzyskać, gdy są one załadowane do openGL, faktycznie używać "dużo" pamięci

Fragment:

tekstury, nawet jeśli są one wykonane z skompresowanych obrazów, należy użyć dużo pamięci sterty Twojej aplikacji ponieważ muszą zostać rozszerzony w pamięci na używany. Każdy piksel zajmuje cztery bajty, , więc zapominając o zwolnieniu tekstury, dane obrazu mogą szybko pochłonąć pamięć Twojego telefonu .

Po drugie, możliwe jest debugowanie pamięci tekstury za pomocą instrumentów. Dostępne są dwie konfiguracje profilowania: OpenGL ES Analyzer i OpenGL ES Driver. Będziesz musiał uruchomić je na urządzeniu, ponieważ symulator nie korzysta z OpenGL. Po prostu wybierz Product-> Profile from XCode i poszukaj tych profili po uruchomieniu Instruments.


Uzbrojony w tę wiedzę, tutaj jest to, co chciałbym zrobić:

  • Sprawdź, czy nie jesteś leaking memory - to oczywiście powodować ten problem.
  • Upewnij się, że nie jesteś accessing autoreleased memory - częstą przyczyną awarii.
  • Utwórz osobną aplikację testową i graj z ładowaniem tekstur pojedynczo (w połączeniu), aby sprawdzić, która tekstura (lub ich kombinacja) powoduje problem.

UPDATE: Po myślenie o swoim pytaniu Czytałem Apple's OpenGL ES Programming Guide i ma bardzo dobre informacje. Wysoce polecany!

+0

Link do artykułu jest martwy, każdy pomysł, gdzie mogę znaleźć te informacje? – cheeesus

+0

Dodałem trochę informacji dotyczących tego, o czym mówił artykuł. Usunąłem także martwy link. – bentford

+0

Patrzę na konfiguracje OpenGL ES Analyzer i OpenGL ES Driver i nie mogę znaleźć ilości używanej pamięci tekstury. W jaki sposób uzyskuje się faktyczną pamięć tekstur OpenGL dla aplikacji na iOS? –

0

To nie jest specjalnie pomocne, ale jeśli okaże się, że narzędzia pamięci nie dostarczają wszystkich potrzebnych danych, należy zgłosić błąd na stronie bugreport.apple.com. Dołącz kopię swojej aplikacji i opis, w jaki sposób narzędzia nie spełniają Twoich oczekiwań, a Apple zobaczy, czy mogą ulepszyć narzędzia. Dzięki!

2

Hrmm, to nie wiele szczegółów, ale jeśli przecieki nie pokazać, gdzie są przecieki, istnieją dwie ważne opcje:

[i] Wycieki brakowało przeciek [ii] Pamięć nie jest faktycznie wyciekła

Naprawienie [i] jest dość trudne, ale jak Eric Albert powiedział, że zgłoszenie błędu w Apple pomoże. [ii] oznacza, że ​​pamięć, której używasz, jest wciąż dostępna gdzieś, ale być może zapomniałeś o tym. Czy jakaś lista rośnie, bez wyrzucania starych wpisów? Czy wszystkie bufory są często realloc()?

+0

Każdy kod zamknięty w nawiasach połączenia wywołującego z GCD jest chroniony przed dwiema rzeczami: raportowaniem błędów i czasami liczeniem alokacji. To zwykle dotyczy tylko CoreFoundation lub jakiejkolwiek innej rzeczy, która nie jest UIKit lub nie-NSFoundation. –

3

Jednym ze sposobów jest rozpoczęcie komentowania kodu i sprawdzenie, czy błąd nadal występuje. Tak, jest to nudne i elementarne, ale może pomóc, gdybyś wiedział, gdzie jest błąd.

Gdzie jest upaść dlatego jest upaść, itp

+0

Niestety to nie działa, nie mogę po prostu skomentować alokacji i mam nadzieję, że aplikacja tego nie zauważy. – zoul

+0

Właściwie to nie jest zła rada. Jeśli aplikacja zużywa coraz więcej pamięci, możliwe jest skomentowanie fragmentów kodu alokacji pamięci i zawężenie potencjalnych podejrzanych do pojedynczej klasy lub linii. – zoul

2

Dla tych, widząc to po roku 2012:

Pamięć naprawdę ładowane do pamięci fizycznej urządzenia jest rezydentny w VM Tracker instrumentu.

Instrument alokacji zaznacza tylko pamięć utworzoną przez malloc/[NSObject alloc] i pewien bufor struktury, na przykład, zdekompresowana bitmapa obrazu nie jest zawarta w Allocation Instrument, ale zawsze zajmuje większą część twojej pamięci.

Proszę obejrzeć sesję WWDC 2012 242 Wydajność aplikacji iOS: Pamięć, aby uzyskać informacje od firmy Apple.