菜鸟教程小白 发表于 2022-12-13 02:24:00

iOS 应用程序在下载非常大的文件时耗尽内存


                                            <p><p>我知道我的问题的变体已在此处以一种或另一种形式提出了很多次 - 我已经广泛搜索这些帖子好几天了,我认为我的问题是独一无二的。请允许我描述一下:</p>

<p>我在 iPad 4 上有一个 iOS 应用程序,可以将一个大文件(260MB 到 650MB)下载到磁盘。下载期间的内存使用量与下载的数据量成正比。大约 500MB 时,应用会收到内存不足警告,大约 650MB 时会因内存不足而被终止。</p>

<p>我反复使用 Instruments 来尝试追踪分配的来源 - 我已经多次运行分配、VM 分配、泄漏、内存监视器和事件监视器。随着内存的增加,我也拍了很多照片。 Instruments 从未显示来 self 的应用程序的大量分配!内存保持平坦。泄漏也不会报告任何内容。</p>

<p>相反,我一直依赖于向内核询问内存使用情况的一组函数,我在此处的另一个线程上找到了这些函数:</p>

<pre><code>   vm_size_t usedMemory(void) {
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    kern_return_t kerr = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&amp;info, &amp;size);
    return (kerr == KERN_SUCCESS) ? info.resident_size : 0; // size in bytes
}

vm_size_t freeMemory(void) {
    mach_port_t host_port = mach_host_self();
    mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
    vm_size_t pagesize;
    vm_statistics_data_t vm_stat;

    host_page_size(host_port, &amp;pagesize);
    (void) host_statistics(host_port, HOST_VM_INFO, (host_info_t)&amp;vm_stat, &amp;host_size);
    return vm_stat.free_count * pagesize;
}

void logMemUsage(void) {
    // compute memory usage and log if different by &gt;= 100k
    static long prevMemUsage = 0;
    long curMemUsage = usedMemory();
    long memUsageDiff = curMemUsage - prevMemUsage;

    // if (memUsageDiff &gt; 100000 || memUsageDiff &lt; -100000) {
    prevMemUsage = curMemUsage;
    //NSLog(@&#34;Memory used %7.1f (%+5.0f), free %7.1f kb&#34;, curMemUsage/1000.0f, memUsageDiff///1000.0f, freeMemory()/1000.0f);
    printf(&#34;Memory used %7.1f (%+5.0f), free %7.1f kb\n&#34;, curMemUsage/1000.0f, memUsageDiff/1000.0f, freeMemory()/1000.0f);

    //}
}
</code></pre>

<p>使用它让我终于看到 <em>something</em> 在下载循环中消耗了内存。我正在使用 RequestQueue 以及以下方法进行下载:</p>

<pre><code>- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    if (_filePath &amp;&amp; _filePath.length)
    {
      if (_fileHandle == nil)
      {
            [ createFileAtPath:_filePath contents:nil attributes:nil];
            self.fileHandle = ;
            _bytesWritten = _rangeStart;
      }

      ;
      _bytesWritten += ;
      NSInteger totalBytes = MAX(0, _responseReceived.expectedContentLength) + _rangeStart;

      if (_downloadProgressHandler)
      {
            _downloadProgressHandler(_userData, _userData2, (float)_bytesWritten / (float)totalBytes, _bytesWritten, totalBytes);
      }
    }
}
</code></pre>

<p>即使我注释掉 <code></code> 调用,我仍然观察到内存增加!我仔细检查了我正在关闭文件句柄并在完成后将其设置为 nil,但在下载期间内存正在增长。</p>

<p>注意:此项目使用 ARC。 </p>

<p>目前我没有东西可以尝试。根本不将数据写入文件仍然会导致内存增长。禁用显示下载进度的 <code>UIStatusBar</code> 没有帮助。我在 Instruments 中看不到任何东西。我打算尝试使用 <code>NSOutputStream</code> 来写入文件,但我怀疑这是否会有所帮助,因为根本不写入数据仍然会导致内存增长。</p>

<p>我尝试使用 <code>NSURLCache</code> 并在收到内存不足警告时清除缓存。我尝试将 nil 分配给 <code>didReceiveData</code> 方法中的数据,但这并没有改变任何东西。我还尝试将尽可能多的强指针更改为弱指针,但这只会导致选择器在已释放的实例上被调用。</p>

<p>现在非常欢迎任何建议。</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>您在 Instruments 中看不到它的事实表明您的 Release 和 Debug 配置之间存在显着差异。您是否在 Instruments 下收到内存警告?</p>

<p>编辑您的方案,选择“配置文件”选项并选择构建配置“调试”。看看这是否与您使用“运行”时看到的相符。如果是这样,那么您可以从那里使用 Instruments 来追踪它。</p>

<p>这是一个远景,但要验证的一件事是您没有意外打开 NSZombies。如果你这样做了,你会看到这种行为。转到您的方案并检查“运行”选项。查看“诊断” Pane 并确保未选择任何内容。</p></p>
                                   
                                                <p style="font-size: 20px;">关于iOS 应用程序在下载非常大的文件时耗尽内存,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/16113426/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/16113426/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: iOS 应用程序在下载非常大的文件时耗尽内存