Obserwowałem tylko to zachowanie na iOS 9; iOS 8 działa poprawnie.Dlaczego plik CIContext.createCGImage powoduje wyciek pamięci?
Podejrzewam, że to może być błąd w SDK i otworzyłem radar do Apple (22644754), ale uważam, że jest to tak dziwne, że mam wrażenie, że może brakować połączenia lub kroku do uniknij wycieku.
Zaobserwowałem, że za każdym razem, gdy wywoływany jest CIContext.createCGImage, wzrasta użycie pamięci. Trudne jest to, że wzrost pamięci występuje poza aplikacją.
Jeśli przyjrzeć się "Raportowi z pamięci" z Xcode, zwiększenie pamięci jest widoczne w sekcji "Inne procesy".
Zasadniczo, co zrobić, aby spowodować problem jest następujący (mam uproszczony kod ściśle elementy niezbędne do reprodukcji wyciek):
Najpierw tworzę CIContext poparte EAGLContext:
let glContext = EAGLContext(API: .OpenGLES2)!
let ciContext = CIContext(EAGLContext: glContext, options: [kCIContextOutputColorSpace : NSNull()])
Potem renderowanie obrazu przy użyciu następujących:
let input = CIImage(image: UIImage(named: "DummyImage")!)!
ciContext.createCGImage(input, fromRect: input.extent)
DummyImage jest tylko przykładowy plik obrazu. Wyciek jest bezpośrednio związany z rozmiarem tego obrazu, więc najlepiej jest użyć dużego, aby problem był bardziej zauważalny.
Jak widać, nie używam żadnych CIFILterów (używanie ich powoduje taki sam wynik) i nie przechwytywam uzyskanego obrazu (nawet jeśli zrobiłem to, nie mogłem użyć CGImageRelease jako obiektów są automatycznie zarządzane).
Jeśli kod renderowania zostanie wykonany wystarczająco długo, pamięć będzie rosnąć tak bardzo, że uruchomione aplikacje zostaną zabite.
Jedną z interesujących obserwacji jest to, że niszczenie CIContekstu nie ma znaczenia, ale niszczenie EAGLContekstu powoduje zwrócenie pamięci. To sprawia, że myślę, że wyciek ma miejsce po stronie OpenGL.
Czy brakuje mi kodu, który może spowodować wyciek? Czy jest jakaś rozmowa, którą mogę wykonać, aby zwolnić pamięć pobraną przez EAGLContext? (Odtwarzanie go przez cały czas nie jest opcją, ponieważ jest to kosztowna operacja).
Stworzyłem prosty projekt do odtworzenia problemu. Można go znaleźć pod adresem:
https://www.dropbox.com/s/zm19u8rmujv6jet/EAGLContextLeakDemo.zip?dl=0
kroki prowadzące do odtworzenia są:
- Otwórz i uruchomić załączony projekt na urządzeniu.
- Obserwuj ekran "Raport o pamięci" w Xcode. Wzrost będzie widoczny na wykresie kołowym "Inne procesy" na wykresie "Porównanie wykorzystania".
- Aplikacja zawiera trzy przyciski. Każdy z nich wykona komendę createCGImage określoną liczbę razy (pokazaną na etykietach przycisków).
- Naciśnięcie dowolnego przycisku spowoduje zwiększenie wykorzystania pamięci w "Inne procesy". Może to być bardziej zauważalne po wykonaniu kilku wywołań createCGImage.
- Stuknięcie na przyciskach 100 Rendry pokaże wyraźniejszy efekt.
- Gdy wzrost pamięci jest nadmierny, aplikacja ulegnie awarii.
dlaczego 'bytesPerPixel = 8'? Czy format 'kCIFormatRGBA8' nie jest 4-bajtowy na piksel? –