2015-10-31 125 views
3

在我的应用程序(OS X应用程序)中,我在短时间内发送大约5,000个URL请求,以从服务器检索JSON对象。我同时发送50个请求,等待所有请求完成,然后再发送50个批次。但是我有一些内存管理问题...NSURLSession - 高内存使用率

当所有请求都完成时(〜2分钟),我的应用程序增加了大约250MB的内存使用量,并且这个内存永远不会被释放。我使用NSURLSession/dataTaskWithURL来获取数据,为了排除故障,我从完成处理程序中删除了所有代码 - 它只是触发请求并放弃响应。这里有一个例子:

func fetchData() { 
    let config = NSURLSessionConfiguration.ephemeralSessionConfiguration() 
    // Also tried .defaultSessionConfiguration() 
    config.URLCache = nil 
    config.HTTPCookieAcceptPolicy = .Never 
    config.HTTPCookieStorage = nil 
    let session = NSURLSession(configuration: config) 

    let query = session.dataTaskWithURL(myURL) { (data, response, error) -> Void in 
     session.invalidateAndCancel() 
     // Normally call a completion handler here too 
    } 
    query.resume() 
} 

请注意,我禁用所有缓存和cookie,以及调用invalidateAndCancel()当请求已经完成。我也尝试过使用标准sharedSession(),但没有任何区别 - 内存使用量总是迅速攀升并永久保持高速。

这是一个很大的问题,因为我的应用程序需要定期发送这些请求,并且每次循环时内存都会攀升得更高 - 最终会达到几GB的内存。还应该注意的是,一旦内存使用达到这一点,我的程序就会慢慢爬行。

有谁知道为什么NSURLSession可能会保留这么多的内存?使用仪器进行分析不会发现任何内存泄漏,所以我非常难以忍受。任何帮助或建议将不胜感激。

+0

有关您为什么需要5000个会话的更多信息?听起来你在这里与iOS工作,这是一个疯狂的高数字? – Ben

+0

@Ben这是一个Mac应用程序,而不是iOS应用程序。基本上,它全天候运行并对大量数据进行分析。这是很多要求,但机器自然有互联网连接来处理它。我还应该提到,我试过重复使用会话,而不是为每个请求创建一个新会话,但无济于事。 – hundley

回答

0

你有没有尝试设置

Config = nil 
Query = nil 
Session = nil 
[session finishTasksAndInvalidate] 

年末?但是我个人更关心为什么你需要提出5000个请求?好像坏的设计给我...

+0

我试了一下,除了查询之外,因为它不能在它自己的完成处理程序中设置为零。但它仍保留相同数量的内存。为了回应这个设计,我将在这里为未来的读者提及这一点:这是一个全天候运行的Mac应用程序,收集大量数据并对这些数据执行不同类型的分析。数据来自多个来源,并非所有数据都支持批量提取,所以(不幸的是)5,000个请求是完全必要的。 – hundley

+0

您是否尝试将它们设置为在query.resume之后而不是在块内? – Ben

+0

是的,我试图在query.resume()之后将它们设置为零 - 没有区别。 – hundley

2

两件事情:

  1. 由于您使用NSURLSession,确保你没有实例为每个5000个请求一个新的。实例化一个然后再使用它。或许可以尝试使用NSURLSession.sharedSession()

    我见过的每个会话适度内存消耗,如果你有会话的非凡数字,它可以积少成多

  2. 你说你跑仪器寻找泄漏。如今,你很少会发现任何异常的东西。但你也应该寻找有力的参考周期,类似像在时间分析两点之间分配或几代人,并确定为250MB 什么帐户,然后看到它的分配等

    见WWDC的视频,例如作为2013年的Fixing Memory Issues或2012年的iOS App Performance: Memory(并且忽略了iOS中的事实;因为许多这些原则在MacOS上同样适用),这将说明如何诊断这些问题。

+0

我已经缩小了一点问题。如果我尝试同时发送多个请求,它会很快耗尽内存。例如,我会同时发送50个请求,等待所有50个完成,然后发送下一批。这导致高内存使用率,永远不会被释放。但是一次只发送一个请求,连续5000个,不会占用太多内存。问题是,完成需要更长的时间。任何想法为什么并发请求吃内存?我发现创建一个会话(不使用sharedSession)并重用它会给出最好的结果,就像你所建议的那样。 – hundley

+0

当运行并发请求时(无论如何,我一次不会超过4或5个),你的峰值内存使用量应该会增加,但是当这些请求完成时它应该被释放。当你查看没有被释放的分配时,你发现了什么? – Rob

+0

我认为我需要做更多关于使用仪器的研究,因为我不完全确定如何解释我在配置中看到的内容。我一定会期望在请求发生时内存使用量会激增,但奇怪的是,它们在完成时没有被释放。 – hundley