2017-12-26 7 views
0

Ich habe eine scheinbar harmlose Änderung an meiner iOS-App vorgenommen, und die App stürzt ab, weil der Speicherverbrauch ständig ansteigt, während die App läuft, bis sie abstürzt. Dies ist vielleicht eine 10-fache Erhöhung des Speicherverbrauchs.Wie finde ich heraus, welche Klasse am meisten Speicherplatz benötigt?

Wie finde ich heraus, welche Klasse oder Struktur dafür verantwortlich ist? Ich bin auf der Suche nach so etwas wie:

CVPixelBuffer: 800MB CMSampleBuffer: 100MB CIImage: 50MB

ich in beide Xcode Speicher-Debugger geschaut und Instrumenten, aber nichts gefunden.

+0

Haben Sie versucht, irgendein Speicherleck in der App zu finden? –

+1

Vielleicht haben Sie einen Speicher-Typ als eine lokale Variable eingeführt, wahrscheinlich würden Kandidaten Strukturen und wahnsinnig große C-Arrays sein, die theoretisch Ihren Stack-Platz erschöpfen könnten. Wahrscheinlich ist es eine enge Schleife, die etwas auf den Haufen wirft. Haben Sie keine Änderungshistorie, um die Änderung einzuschränken, die das Problem verursacht? –

+0

@ Kamil.S Ich weiß, was zu tun, und es ist noch nicht einmal Git verpflichtet. Es geht nicht um Stack-Speicherplatz, da ich keine tiefe Rekursion habe. Indem ich den neuen Code mühsam auskommentierte und Zeile für Zeile auskommentierte, stellte ich fest, dass das Problem in https://developer.apple.com/documentation/coreimage/cifilter/2138288-init ist. Wenn ich einen CIFilter erstelle und ihn wegwerfe, es leert Speicher, was nicht passieren sollte. Aber gibt uns Xcode oder Instruments einen besseren Weg, nämlich alle Klassen nach Speicher zu sortieren (kumulativ nach allen Instanzen dieser Klasse)? –

Antwort

0

Es ist ein Speicherleck im CIFilter initialiser. Hier sind die Schritte zu reproduzieren:

  1. Verwenden Sie AVFoundation, um einen rohen Probenpuffer zu erfassen.
  2. Anruf CMSampleBufferGetImageBuffer() eine CVPixelBuffer erhalten:
  3. erstellen CIFilter:
  4. Beachten Sie, dass der CIFilter weggeworfen wird.
  5. Nachdem alle oben genannten Schritte abgeschlossen sind, gehen Sie zurück zu Schritt 1 und wiederholen Sie 100 Mal.

Hier ist der Code:

let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer)! 
let metadata = CMCopyDictionaryOfAttachments(nil, sampleBuffer, kCMAttachmentMode_ShouldPropagate)! 
_ = CIFilter(cvPixelBuffer: pixelBuffer, properties: metadata) 

Erwartete Ergebnisse:

ein Swift-Objekt erstellen und wirft es weg nicht ein Speicherleck.

Tatsächliche Ergebnisse:

  • Speichernutzung wächst in unbeschränkter Weise auf mehr als ein Gigabyte, bis iOS die App tötet.
  • Das Auskommentieren der Zeile, die den CIFilter erstellt, beseitigt dieses Problem.
  • Das Konvertieren des RAW-Beispielpuffers in NSData mithilfe von DngPhotoDataRepresentation() und das Übergeben an den CIFilter-Initialisierer beseitigt dieses Problem, scheint jedoch langsamer.
  • Der CVPixelBuffer scheint nicht veröffentlicht zu sein, weil CIFilter (oder irgendein anderer interner Code zu iOS ist). Ich habe überprüft, indem ich eine schwache Referenz zu CVPixelBuffer erstellt habe. Wenn der Puffer freigegeben wird, sollte die schwache Referenz zu Null werden, aber nicht.
  • eine BGRA Capturing (anstelle von RAW) Probenpuffer und in eine CIImage Umwandlung nicht undicht Speicher:

    _ = CIImage (cvImageBuffer: Pixelpuffer, Optionen: [kCIImageProperties: Metadaten])

Dies ist auf iOS 11 auf iPhone 7 Plus und iPhone X.

Verwandte Themen