2012-05-13 6 views

Odpowiedz

21

Tak jak w przypadku innych optymalizacji wydajności, powinieneś generalnie dodawać tylko dodatkowe pule autorelease do kodu, jeśli zauważysz wysokie użycie pamięci i profilowanie (na przykład przy użyciu Instrumentów) prowadzi do dodatkowych puli autoreasowania jako rozwiązania.

Powiedziawszy, możesz owijać kod, który tworzy dużą liczbę tymczasowych obiektów w ciasnej pętli w puli autorelease. Domyślna pula autoreleaseu jest opróżniana pod koniec cyklu pętli. Tak więc, jeśli tworzysz dużo tymczasowych obiektów w każdej iteracji pętli for w kodzie, domyślna pula autorelease nie zostanie wyczerpana, dopóki cała twoja pętla nie zostanie uruchomiona, co oznacza, że ​​wszystkie utworzone tymczasowe obiekty mogą sumować się do wysokie zużycie pamięci tymczasowej (czasami nazywane "wysokim znakiem wody"). Możesz zawinąć każdą iterację pętli w @autoreleasepool, aby spowodować niepotrzebne, autoreleased, tymczasowe obiekty utworzone w tej iteracji pętli, które zostaną wcześniej wydane.

+0

Uratowałeś mnie. Posiadam długą metodę obliczeniową, która tworzy wiele liczb w kilku pętlach. W instrumentach wykorzystanie pamięci ogromnie rośnie i spada po zakończeniu obliczeń. Czy jest jakaś wada przy użyciu '@ autorelease' do owijania pojedynczych pętli? To nie jest naprawdę zalecane przez Apple, prawda? – JFS

+2

Jest to zalecane przez firmę Apple w przypadkach, w których jest to właściwe. Zobacz dokumentację tutaj: https://developer.apple.com/library/ios/DOCUMENTATION/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html –

+0

Andrew, jesteś po prostu niesamowity! Miałem ból głowy z powodu tego problemu z pamięcią, dopóki nie znalazłem tej sugestii. Jest prosty i działa po prostu niesamowicie. Mogę teraz zezwolić na więcej obliczeń w mojej aplikacji. DZIĘKI! – JFS

1

Wszystkie autoreleased obiekty są technicznie umieszczane w puli autorelease. Zwykle jest to domyślna funkcja utworzona wewnątrz głównej funkcji. Jeśli chodzi o zawijanie obiektów w niewymienną pulę autorelease, zwykle odbywa się to jako optymalizacja.

Zwykle nie ma potrzeby korzystania z jawnej puli autorelease, ponieważ domyślna pula autorelease jest automatycznie opróżniana w pętli uruchamiania aplikacji. Jednakże, jeśli masz aplikację, która tworzy wiele autoreleased obiektów zanim powróci z twoich programów obsługi zdarzeń, może użyć dużej ilości pamięci dla tych obiektów. Jeśli więc zawiniesz swój kod do jawnej puli autorelease, zostaną umieszczone tam autorefleksowane obiekty zamiast domyślnej puli. Umożliwia to okresowe opróżnianie tej puli, aby zapobiec gromadzeniu się autoreleased obiektów.

12

Aby rozszerza dotychczasowe odpowiedzi:

Pula automatycznego uwalniania jest używany do wysyłania wiadomości release automatycznie do obiektów dodanych do niego.

W programie iOS lub Cocoa pulę automatycznego uwalniania jest automatycznie tworzona w wątku głównym i jest opróżniana na końcu pętli uruchamiania.

Powiedziawszy, pula automatycznego wydania jest obowiązkowa, gdy używa się obiektów z automatycznym zwolnieniem w innym wątku.

Więc jeśli odłączysz wątek od jakiejś metody, włóż swój gwintowany kod do puli automatycznego wydania. W przeciwnym razie automatycznie zwolnione obiekty utworzone w wątku po prostu wyciekną.

Innym zastosowaniem puli automatycznej dystrybucji jest optymalizacja części kodu, które będą zużywać dużo pamięci, dzięki czemu zostaną zwolnione przed końcem pętli uruchamiania.

Ale dotyczy to tylko obiektów zwolnionych automatycznie.

Na przykład:

- (void)test 
{ 
    NSMutableArray * a = [ [ NSMutableArray alloc ] init ]; 

    [ a release ]; 
} 

Nie potrzeba puli auto uwalnianiu tutaj, jak nie masz obiektu automatycznego zwolniony.
Zmienna a zostanie zwolniona natychmiast, ponieważ została jawnie przydzielona i zwolniona.

Teraz:

- (void)test 
{ 
    NSMutableArray * a = [ NSMutableArray arrayWithCapacity ]; 
} 

Tutaj używasz konstruktora wygody, co oznacza, że ​​nie mają prawa własności na tym obiekcie.
Oznacza to również, że obiekt został dodany do aktualnej puli automatycznej wersji (jeśli taka istnieje).

tak będzie uwolniony, gdy ten basen auto-release jest odprowadzana, więc może to potrwać kilka cykli ...

Jeśli część kodu piszesz zużywa dużo pamięci, można użyć innego autorelease basen, dzięki czemu auto wydany obiekty są zwalniane, gdy metoda przywracany:

- (void)test 
{ 
    @autoreleasepool 
    { 
     NSMutableArray * a = [ NSMutableArray arrayWithCapacity ]; 
    } 
} 
0

Istnieją jednak sytuacje, kiedy trzy, można użyć własnych bloków puli autorelease:

  1. Jeśli piszesz program, który nie jest oparty na strukturze interfejsu użytkownika, na przykład na narzędziu wiersza polecenia.

  2. Jeśli napiszesz pętlę, która tworzy wiele tymczasowych obiektów. Możesz użyć bloku puli autorelease wewnątrz pętli, aby pozbyć się tych obiektów przed następną iteracją. Korzystanie z bloku puli autorelease w pętli pomaga zmniejszyć maksymalny rozmiar pamięci aplikacji.

  3. Jeśli pojawi się dodatkowy wątek.

Powiązane problemy