Ios NSURLSession-内存使用率高

Ios NSURLSession-内存使用率高,ios,swift,macos,memory,nsurlsession,Ios,Swift,Macos,Memory,Nsurlsession,在我的应用程序(OSX应用程序)中,我在短时间内发送大约5000个URL请求,以从服务器检索JSON对象。我同时发送50个请求,等待所有请求完成,然后再发送另一批50个请求。但是我有一些内存管理问题 当所有请求都完成时(约2分钟),我的应用程序的内存使用量增加了约250MB,而这些内存从未释放。我正在使用NSURLSession/dataTaskWithURL获取数据,为了排除故障,我已经从完成处理程序中删除了所有代码——它只是触发请求并丢弃响应。下面是一个例子: func fetchData(

在我的应用程序(OSX应用程序)中,我在短时间内发送大约5000个URL请求,以从服务器检索JSON对象。我同时发送50个请求,等待所有请求完成,然后再发送另一批50个请求。但是我有一些内存管理问题

当所有请求都完成时(约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的RAM。还应该注意的是,一旦内存使用达到这一点,我的程序就会慢到爬行状态

有人知道为什么
NSURLSession
会保留这么多内存吗?使用仪器进行分析不会发现任何内存泄漏,所以我在这里很困惑。如果您有任何帮助或建议,我们将不胜感激。

您尝试过设置吗

Config = nil
Query = nil
Session = nil
[session finishTasksAndInvalidate]
最后呢?但就我个人而言,我更关心的是为什么你需要提出5000个请求?对我来说,这似乎是个糟糕的设计…

两件事:

  • 由于您使用的是
    NSURLSession
    ,请确保没有为这5000个请求中的每个请求实例化一个新的会话。实例化一个,然后重用它。也许可以尝试改用
    NSURLSession.sharedSession()

    我已经看到每个会话的内存消耗是适度的,如果您有非常多的会话,它可以加起来

  • 你说你用仪器寻找漏洞。如今,你很少会发现像这样令人震惊的事情。但是,您还应该通过分析两个时间点之间的分配或生成来寻找强引用周期等,并确定250mb的原因,然后查看分配的位置,等等

    查看WWDC视频,例如2013年或2012年的视频(并且忽略iOS在标题中的事实;因为这些原则中的许多同样适用于MacOS),这些视频将说明如何诊断此类问题


  • 关于你为什么需要5000次治疗的更多信息?听起来你是在反对iOS,这是一个疯狂的数字?@Ben这是一个Mac应用程序,不是iOS应用程序。基本上,它全天候运行,并对大量数据进行分析。这是一个很大的请求,但机器自然有互联网连接来处理它。我还应该提到,我尝试过重用会话,而不是为每个请求创建一个新的会话,但没有效果。我尝试了一下,除了query,因为它不能在自己的完成处理程序中设置为nil。但它仍然保留了相同的内存量。作为对该设计的回应,我将在这里向未来读者介绍这一点:这是一个全天候运行的Mac应用程序,它收集大量数据并对这些数据执行不同类型的分析。数据来自多个来源,并非所有来源都支持批量获取,因此(不幸的是)5000个请求是完全必要的。您是否尝试在query.resume之后将它们设置为nil,而不是在块中?是的,我也尝试在query.resume()之后将它们设置为nil-没有区别。这包括:[session FinishTasks and Invalidate我已经缩小了问题的范围。如果我尝试同时发送多个请求,它会很快占用内存。例如,我会同时发送50个请求,等待所有50个请求完成,然后发送下一批。这会导致高内存使用率,永远不会释放。但一次只发送一个请求一次,连续5000次,不会占用太多内存。问题是,它需要更长的时间才能完成。你知道为什么并发请求会占用内存吗?我发现创建一个会话(不使用sharedSession)并重用它会得到最好的结果,正如你所建议的。当运行并发请求时(无论如何,我一次最多只能做4到5件事),您的峰值内存使用率应该会增加,但当这些请求完成时,它应该会被释放。当您查看未释放的分配时,您发现了什么?我想我需要对使用工具进行更多的研究,因为我不完全确定如何解释我在分配中看到的内容。我当然希望内存使用率会达到峰值w有人提出请求,但奇怪的是,请求完成后却没有被释放。我上面提到的WWDC视频是很好的、实用的介绍。其中包括使用工具跟踪问题的良好演示。