GCD dispatch_async Speicherleck?

8

Der folgende Code belegt ~ 410 MB Speicher und gibt ihn nicht wieder frei. (Die Version mit dispatch_sync anstelle von dispatch_async benötigt ~ 8MB Speicher)
Ich würde eine Spitze von hohem Speicherverbrauch erwarten, aber es sollte wieder sinken ... Wo ist das Leck?

%Vor%

Ich habe es versucht:

  • Hinzufügen von @autoreleasepool um und innerhalb der Schleife
  • Hinzufügen von NSRunLoop run zur Schleife

Ich habe mehrere Kombinationen ausprobiert und nie eine Verringerung des Gedächtnisses festgestellt (selbst nach Minuten). Ich kenne den GCD-Referenzleitfaden, der die folgende Aussage enthält:

  

Obwohl GCD-Versandwarteschlangen ihre eigenen Autorelease-Pools haben, geben sie keine Garantie, wann diese Pools leer sind.

Gibt es in diesem Code ein Speicherleck? Wenn nicht, gibt es eine Möglichkeit, die Warteschlange zu erzwingen, um die fertigen Blöcke freizugeben / zu leeren?

    
Andreas 16.02.2015, 08:55
quelle

2 Antworten

1

Objective-C Block es ist eine C-Struktur, ich denke, Sie erstellen 100000 die Blockobjekte, um sie in Hintergrundthreads auszuführen und sie warten, während das System sie ausführen kann. Ihr Gerät kann eine begrenzte Anzahl von Threads ausführen. Dies bedeutet, dass viele Blöcke warten, bevor das Betriebssystem sie startet.

Wenn Sie "async" in "sync" ändern, wird ein nächstes Blockobjekt erstellt, nachdem ein vorhergehender Block beendet und zerstört wurde.

UPD

Über den GCD-Pool.

GCD führt Aufgaben im GCD-Thread-Pool aus, Threads werden vom System erstellt und vom System verwaltet. Das System speichert Threads zwischen, um CPU-Zeit zu sparen. Jeder Dispatch-Task wird im freien Thread ausgeführt.

Aus der Dokumentation:

-

Blöcke, die an Versandwarteschlangen gesendet werden, werden in einem Pool von Threads ausgeführt, der vollständig vom System verwaltet wird. Es gibt keine Garantie für den Thread, auf dem eine Aufgabe ausgeführt wird.

-

Wenn Sie die Aufgaben als synchronisierte Aufgaben ausführen, besteht der freie Thread (aus dem GCD-Thread-Pool) zur Ausführung der nächsten Aufgabe, nachdem die aktuelle Aufgabe beendet wurde (weil der Haupt-Thread während der Ausführung der Aufgabe wartet und keine neuen Aufgaben hinzufügt) Warteschlange), und das System weist keinen neuen NSThread zu (Auf meinem Mac habe ich 2 Threads gesehen). Wenn Sie die Aufgaben als async ausführen, kann das System viele NSThreads zuweisen (um maximale Leistung zu erreichen, befinden sich auf meinem Mac fast 67 Threads), da die globale Warteschlange viele Aufgaben enthält.

Hier können Sie über die maximale Anzahl von GCD-Thread-Pools lesen.

Ich habe in Alocations Profiler gesehen, dass viele NSThreads zugewiesen und nicht zerstört sind. Ich denke, es ist ein Systempool, der bei Bedarf freigegeben wird.

    
Andrew Romanov 16.02.2015 09:16
quelle
0

Setzen Sie @autoreleasepool immer in jeden GCD-Anruf und Sie werden keine Probleme haben. Ich hatte das gleiche Problem und dies ist die einzige Problemumgehung.

%Vor%     
manta 01.10.2016 12:12
quelle