我知道我的问题的变体已在此处以一种或另一种形式提出了很多次 - 我已经广泛搜索这些帖子好几天了,我认为我的问题是独一无二的。请允许我描述一下:
我在 iPad 4 上有一个 iOS 应用程序,可以将一个大文件(260MB 到 650MB)下载到磁盘。下载期间的内存使用量与下载的数据量成正比。大约 500MB 时,应用会收到内存不足警告,大约 650MB 时会因内存不足而被终止。
我反复使用 Instruments 来尝试追踪分配的来源 - 我已经多次运行分配、VM 分配、泄漏、内存监视器和事件监视器。随着内存的增加,我也拍了很多照片。 Instruments 从未显示来 self 的应用程序的大量分配!内存保持平坦。泄漏也不会报告任何内容。
相反,我一直依赖于向内核询问内存使用情况的一组函数,我在此处的另一个线程上找到了这些函数:
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)&info, &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, &pagesize);
(void) host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size);
return vm_stat.free_count * pagesize;
}
void logMemUsage(void) {
// compute memory usage and log if different by >= 100k
static long prevMemUsage = 0;
long curMemUsage = usedMemory();
long memUsageDiff = curMemUsage - prevMemUsage;
// if (memUsageDiff > 100000 || memUsageDiff < -100000) {
prevMemUsage = curMemUsage;
//NSLog(@"Memory used %7.1f (%+5.0f), free %7.1f kb", curMemUsage/1000.0f, memUsageDiff///1000.0f, freeMemory()/1000.0f);
printf("Memory used %7.1f (%+5.0f), free %7.1f kb\n", curMemUsage/1000.0f, memUsageDiff/1000.0f, freeMemory()/1000.0f);
//}
}
使用它让我终于看到 something 在下载循环中消耗了内存。我正在使用 RequestQueue 以及以下方法进行下载:
- (void)connectionNSURLConnection *)connection didReceiveDataNSData *)data
{
if (_filePath && _filePath.length)
{
if (_fileHandle == nil)
{
[[NSFileManager defaultManager] createFileAtPath:_filePath contents:nil attributes:nil];
self.fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:_filePath];
_bytesWritten = _rangeStart;
}
[_fileHandle writeData:data];
_bytesWritten += [data length];
NSInteger totalBytes = MAX(0, _responseReceived.expectedContentLength) + _rangeStart;
if (_downloadProgressHandler)
{
_downloadProgressHandler(_userData, _userData2, (float)_bytesWritten / (float)totalBytes, _bytesWritten, totalBytes);
}
}
}
即使我注释掉 [_fileHandle writeData:data] 调用,我仍然观察到内存增加!我仔细检查了我正在关闭文件句柄并在完成后将其设置为 nil,但在下载期间内存正在增长。
注意:此项目使用 ARC。
目前我没有东西可以尝试。根本不将数据写入文件仍然会导致内存增长。禁用显示下载进度的 UIStatusBar 没有帮助。我在 Instruments 中看不到任何东西。我打算尝试使用 NSOutputStream 来写入文件,但我怀疑这是否会有所帮助,因为根本不写入数据仍然会导致内存增长。
我尝试使用 NSURLCache 并在收到内存不足警告时清除缓存。我尝试将 nil 分配给 didReceiveData 方法中的数据,但这并没有改变任何东西。我还尝试将尽可能多的强指针更改为弱指针,但这只会导致选择器在已释放的实例上被调用。
现在非常欢迎任何建议。
Best Answer-推荐答案 strong>
您在 Instruments 中看不到它的事实表明您的 Release 和 Debug 配置之间存在显着差异。您是否在 Instruments 下收到内存警告?
编辑您的方案,选择“配置文件”选项并选择构建配置“调试”。看看这是否与您使用“运行”时看到的相符。如果是这样,那么您可以从那里使用 Instruments 来追踪它。
这是一个远景,但要验证的一件事是您没有意外打开 NSZombies。如果你这样做了,你会看到这种行为。转到您的方案并检查“运行”选项。查看“诊断” Pane 并确保未选择任何内容。
关于iOS 应用程序在下载非常大的文件时耗尽内存,我们在Stack Overflow上找到一个类似的问题:
https://stackoverflow.com/questions/16113426/
|