【问题标题】:NSURLConnection + NSMutableData for file downloads is really slow用于文件下载的 NSURLConnection + NSMutableData 真的很慢
【发布时间】:2010-07-20 12:51:53
【问题描述】:

基本上发生的事情是,我需要在我的应用程序中下载一大堆文件,并且我设置了一个队列,使用 NSURLConnection 下载每个文件,并将服务器响应增量存储在 NSMutableData 中,直到下载完成完成,然后将整个内容写入磁盘。

以下是相关部分:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)_response {
    response = [_response retain];
    if([response expectedContentLength] < 1) {
        data = [[NSMutableData alloc] init];
    }
    else {
        data = [[NSMutableData dataWithCapacity:[response expectedContentLength]] retain];
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)_data {
    [data appendData:_data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    NSLog(@"saved: %@", self.savePath);
    [data writeToFile:self.savePath atomically:YES];
}

关于为什么这会非常慢的任何见解?模拟器非常糟糕,在实际设备上变得更糟。我的最大下载大小约为 2 兆字节,所以我认为将整个内容存储在内存中直到它完成并不是一个坏主意。这最多可以达到大约 20KB/s(使用直接的 ad-hoc wifi 连接)。

编辑:在我所有的测试用例中,我确实得到了一个 Content-Length 标头,所以这不是随着收到的每一位响应而增加 NSMutableData 的问题。

编辑 2:this 是 Shark 给我的全部。

编辑 3:这就是我设置连接的方式

NSMutableURLRequest *request = [[NSMutableURLRequest requestWithURL:[NSURL URLWithString:[@"http://xxx.xxx.xxx.xxx/index.php?service=" stringByAppendingString:service]]] retain];

[request setHTTPMethod:@"POST"];
[request setHTTPBody:[[options JSONRepresentation] dataUsingEncoding:NSUTF8StringEncoding]];

NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:self];
[conn start];

当然,我实际上并没有硬编码的 url,并且 request 和 conn 都是下载器类的实例变量。没关系,但对于 JSON,我使用的是http://code.google.com/p/json-framework/。选项和服务是方法参数(NSString 和 NSDictionary),它们也不重要。

【问题讨论】:

    标签: cocoa-touch ipad nsurlconnection


    【解决方案1】:

    男孩,这很尴尬。结果我的 Content-Length 标头不准确,这导致 NSURLConnection 需要等待某种超时才能完成,即使它拥有所有数据。真的有道理。也许这会帮助其他人。

    【讨论】:

      【解决方案2】:

      我会分析以找出减速发生的位置和模式。在connection:didReceiveData 中添加一条日志语句,以查看它被调用的频率。您正在寻找:

      1. 调用方法之间的相对经过时间。
      2. 调用之间的时间是否随着应用程序的运行而增加。

      如果调用之间的经过时间是应用程序花费大部分时间的地方,那么瓶颈就在请求本身。请求配置错误,服务器没有快速发送。

      如果应用程序运行的时间越长,调用之间的时间就越长,那么这可能是内存问题。随着数据越来越大,内存越来越受限,应用程序必须在内存中交换更多的东西,这会减慢一切。要进行测试,请在任何活动对象中记录各种 didReciveMemoryWarning 方法。


      更新:

      根据 Shark 的说法,问题在于您的 URL 请求,而不是您发布的代码。您需要查看如何设置请求。

      【讨论】:

      • 默认情况下不是全局记录内存警告吗?我没有记录连接之间的时间:didReceiveData,但我确实跟踪了我的 apache 日志,并且各个请求之间的时间是统一的,我的总内存使用量从未超过每次下载的几兆字节,并且每个下载器对象在之后被正确释放完成。我还用 Shark 做了一个时间分析,大部分时间都花在了与 urlconnection 相关的系统调用上。在这种情况下,服务器不是问题,已经单独测试过。
      • 以后,如果您有来自 Shark 等工具的信息并且您控制服务器,则应该在原始问题中包含该信息。否则,我们将假定您没有该信息和/或不知道如何获取它。
      • 我用我用来设置我的请求的代码更新了我的问题。感谢您迄今为止的提示。
      猜你喜欢
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 2023-04-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-12
      相关资源
      最近更新 更多