2016-04-12 31 views
4

有人能澄清一下Swift的內存管理嗎?Swift中的內存管理:NSOperation結束後不會釋放內存

我有以下應用程序的委託:

@NSApplicationMain 
class AppDelegate: NSObject, NSApplicationDelegate { 

    private let _queue = NSOperationQueue() 

    func applicationDidFinishLaunching(aNotification: NSNotification) { 

     _queue.maxConcurrentOperationCount = 1 

     _queue.addOperation(Operation()) 
     _queue.addOperation(Operation()) 
     _queue.addOperation(Operation()) 
    } 
} 

private class Operation: NSOperation { 

    override func main() { 

     autoreleasepool { 

      var d = [String: AnyObject]() 

      for i in 1...1000 { 
       d[i.description] = Repeat(count: 10000, repeatedValue: "ABCDEF").joinWithSeparator("") // tested with repeat or just large string 
      } 

      d.removeAll() 
     } 
    } 
} 

應用程序啓動後,我排隊3個同步操作。每個操作只是創建非常大的字典(結構)與非常大的字符串(也是結構)。

由於所有創建的數據都是數值類型並且沒有捕獲任何數據,我相信內存在主函數結束時應該被釋放。事實上,我加了d.RemoveAll()以防萬一確保內存釋放。

後所有操作完成以下信息活動監視器顯示: enter image description here

我的應用仍然佔據26.7MB,但如果我刪除所有_queue.addOperation(Operation())這將是大約7MB 。所有操作完成後爲什麼還沒有釋放額外的19mb內存?

@Lou佛朗哥 我改變了應用程序的委託來此

func applicationDidFinishLaunching(aNotification: NSNotification) { 
    for _ in 1...100 { 
     _queue.addOperation(Operation()) 
    } 
} 

現在8個作業同時運行。所有操作完成後約40mb未完成。我試圖排隊100000個操作。應用程序不會造成40分鐘的崩潰。它的內存使用量是600 ... 1000mb,但我無法等到所有操作完成。

+0

我會檢查這與泄漏儀器是肯定的。我不知道這個上下文中的內存是分配給對象還是僅僅保留頁面(稍後可能會回收) –

+0

儀器沒有發現泄漏。內存堆分析表明,只有9mb剩下的是持久而非儀器顯示的25mb。據我瞭解內存 - 當系統沒有足夠的內存和私有內存是應用程序實際使用的內存時,可以回收什麼內容。但是我不確定,並且找不到更具體的內容。 –

+0

我會相信泄漏儀器,你沒有泄漏。活動監視器不知道這一點 - 它正在計算爲您的流程保留的內容 - 您無法直接控制它。最好在Xcode中使用Debug Navigator來快速查看應用程序中的內存使用情況。 –

回答

0

你不漏水。這個過程並不會立即讓所有的內存回到操作系統 - 這將是非常浪費和昂貴的。內存返回到malloc空閒內存列表。

運行您的測試代碼我實際上看到內存爬升然後在每個操作完成後下降。

我還懷疑,內存不會返回到操作系統的情況下,它是零散的(一些對象仍然活着在很多空閒字節之間)。您的示例的這種變體會達到幾百MB的高水位標記,然後在操作完成時降至13.8。通過分配連續的緩衝區,我們知道將有大量的大塊準備好返回到操作系統。

@NSApplicationMain 
class AppDelegate: NSObject, NSApplicationDelegate { 

    private let _queue = NSOperationQueue() 

    func applicationDidFinishLaunching(aNotification: NSNotification) { 

     _queue.maxConcurrentOperationCount = 1 

     _queue.addOperation(Operation()) 
     _queue.addOperation(Operation()) 
     _queue.addOperation(Operation()) 
    } 
} 

private class Operation: NSOperation { 

    override func main() { 
     autoreleasepool { 
      let count = 100000000 
      let p = UnsafeMutablePointer<Int>.alloc(count) 
      for i in 0..<count { 
       p.advancedBy(i).initialize(i) 
      } 
      p.destroy(count) 
      p.dealloc(count) 
     } 
    } 
}