2013-10-02 54 views
1

我有一些圖像正在過濾,當我在創建的串行隊列中執行此操作時,會在每個塊完成後釋放內存。當我將這項工作發送到全球GCD隊列時,內存不會釋放並失去控制。全局GCD隊列的內存使用情況

我將這些語句包裝在autorelease塊中,但這似乎沒有什麼區別。

是否由於線程池以某種方式保持對塊的引用?一段時間後,內存獲得釋放,但應用程序將在此之前崩潰與大量的圖像。

爲什麼內存被全局隊列保留,這怎麼可能被修復,所以它在每個塊之後釋放?

+2

你應該發佈你的代碼。從描述中不可能說出來。正如你所看到的,併發隊列的自動釋放語義是不透明的,而不是直接的,所以一般的建議是在@autoreleasepool中封裝塊的內容,你已經完成了。我懷疑得到更多,你將不得不給我們更多的工作。例如,你是否在關閉提交給隊列的完成塊中捕獲這些圖像?如果是這樣,那將延長圖像的生命週期,直到完成塊完成。但是,如果沒有更多信息,很難提供建議。 – ipmcc

+0

原來這是GCD線程池產生的線程負載,每個線程都在內存中保存了一個巨大的過濾映像。我切換到併發操作隊列並嘗試了不同的併發限制,直到內存可管理。 – jarryd

+0

此外,FWIW,如果GCD產生「負載大於3倍核心數量的線程負載」,則可能意味着您提交給它的塊最終被阻塞。更高性能的方法是串行化串行隊列上的I/O,並且只進行並行內存處理。在這方面從GCD獲得幫助的一種方法是使用'dispatch_apply',這將限制併發操作的數量。 IME'dispatch_apply'不會創建超過2個#core線程。 (儘管這並沒有說明可能創建線程的其他併發操作。) – ipmcc

回答

2

你在你的評論中提到GCD似乎創造了太多的線程,導致太多的圖像一次在內存中。如果GCD產生「負載大於3倍的內核數量」的線程負載,則可能意味着您提交給它的塊最終被阻塞(可能在I/O上)。更高性能的方法是串行化串行隊列上的I/O,並且只進行並行內存處理。在這方面從GCD獲得幫助的一種方法是使用dispatch_apply,這將限制併發操作的數量。 IME dispatch_apply不會創建超過2 *個內核線程數。 (雖然這不能解釋可能會產生線程的其他併發操作)。

另外,如您所述,NSOperationQueue允許您指定最大併發任務數,這是另一種方法。