2016-04-12 30 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) 
     } 
    } 
}