测量AFNetworking HTTP GET中的响应时间

时间:2013-05-11 14:40:08

标签: ios ios6 afnetworking nsoperationqueue

我正在尝试使用AFNetworking下载文件时测量每个GET请求所花费的时间。我正在循环中重复下载文件。 我遇到的问题是我测量总时间的方式,它给出了比实际更大的总时间。例如,对于50次下载,它提供72秒,但实际上它只花了大约5秒。我还怀疑5秒太低而不能下载50次(每个文件的下载大小为581 kb)。

在这种情况下,如何有效地测量时间?我需要时间从请求被解雇到收到响应。

下载文件的方法:

- (void) HTTPGetRequest
{    
    startTime = CACurrentMediaTime(); // Start measuring time

    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:http://myServer];
    NSMutableURLRequest *request = [httpClient requestWithMethod:@"GET"
                                                            path:@"/download/Text581KB.txt"
                                                      parameters:nil];
    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
    [httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];

    // Save downloaded file
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *path = [[paths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@"Text581KB.txt"]];
    operation.outputStream = [NSOutputStream outputStreamToFileAtPath:path append:NO];

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        double elapsedTime = (CACurrentMediaTime() - startTime); // Measuring time
        totalTime += elapsedTime; // Measuring total time HERE!
        [results setString:[NSString stringWithFormat: @"Current Transaction Time: %f sec\nTotal Time: %f sec", elapsedTime, totalTime]];
        [_resultLabel performSelectorOnMainThread:@selector(setText:) withObject:results waitUntilDone:NO];
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        NSLog(@"Error: %@", error);
    }];

    [operation setDownloadProgressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {  ((int)totalBytesExpectedToWrite));
        totalDownloadSize += totalBytesExpectedToWrite;
        [_DataTransferredLabel setText:[NSString stringWithFormat:@"Total Download Size: %@", [self getFileSize:totalDownloadSize/1024]]];
    }];

    [operation setCacheResponseBlock:^NSCachedURLResponse *(NSURLConnection *connection, NSCachedURLResponse *cachedResponse) {
        return nil;
    }];
    [operationQueue addOperation:operation];
}

我在viewDidLoad中创建了一个NSOperationQueue:

operationQueue = [NSOperationQueue new];
[operationQueue setMaxConcurrentOperationCount:1]; // using this as I was suspecting downloads were happening in parallel & thus 50 downloads finishing in a few secs

我正在调用HTTPGetRequest方法,如下所示:

- (IBAction)startDownload:(UIButton *)sender {
    totalCount = [[_countText text] longLongValue]; // get # of times to download
    long currentCount = 1;
    completedCount = 0;
    totalTime = 0;
    totalDownloadSize = 0;
    while (currentCount <= totalCount)
    {
        [self HTTPGetRequest];
        [results setString:@""];
        currentCount++;

    }

3 个答案:

答案 0 :(得分:7)

答案 1 :(得分:4)

在计算累积时间(非经过时间)方面,我刚刚创建了一个AFHTTPRequestOperation的子类来捕获开始时间。否则,您将无法准确知道它何时开始:

@interface TimedAFHTTPRequestOperation : AFHTTPRequestOperation

@property (nonatomic) CFAbsoluteTime startTime;

@end

@implementation TimedAFHTTPRequestOperation

- (void)start
{
    self.startTime = CFAbsoluteTimeGetCurrent();

    [super start];
}

@end

(注意我使用CFAbsoluteTimeGetCurrentCACurrentMediaTime;使用您想要的任何内容,但只是保持一致。)

然后在执行下载的代码中,您可以使用此TimedAFHTTPRequestOperation代替AFHTTPRequestOperation

TimedAFHTTPRequestOperation *operation = [[TimedAFHTTPRequestOperation alloc] initWithRequest:request];

然后,该代码的完成块可以使用startTime的{​​{1}}属性来计算给定操作所用的时间并将其添加到总时间中:

TimedAFHTTPRequestOperation

这就是你如何计算[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { TimedAFHTTPRequestOperation *timedOperation = (id)operation; CFTimeInterval elapsedTime = CFAbsoluteTimeGetCurrent() - timedOperation.startTime; self.totalTime += elapsedTime; // Measuring total time HERE! NSLog(@"finished in %.1f", elapsedTime); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; 并将它们一起追加来计算elapsedTime

关于如何知道操作何时完成,我会

  • 修改totalTime以返回HTTPGetRequest;

  • NSOperation创建一个完成操作,然后将所有这些操作添加为依赖项:

    startDownload

实现了几个目标,即创建完成操作,计算总时间(而不是总时间)。

顺便说一下,我还建议从NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{ NSLog(@"finished all in cumulative time: %.1f", self.totalTime); }]; for (NSInteger i = 0; i < totalCount; i++) { NSOperation *operation = [self HTTPGetRequest]; [completionOperation addDependency:operation]; } [self.operationQueue addOperation:completionOperation]; 中提取AFHTTPClient。您应该只为每个应用创建一个。如果您开始使用HTTPGetRequest而不是创建自己的操作队列,这一点尤为重要。我也认为您无需致电enqueueHTTPRequestOperation


您正在registerHTTPOperationClass增加totalElapsed,但elapsedTime是从elapsedTime计算的,startTime本身代表作业首次排队的时间,而不是下载时间实际上开始。请记住,HTTPGetRequest几乎立即返回(已设置elapsedTime)。因此,如果您排队五次下载,我会不会感到惊讶HTTPGetRequest在第一个请求启动之前运行五次(并设置并重置startTime五次)。

问题是你是否正在进行并发下载这个问题更加复杂,如果是这样,你的意思是“总逝去时间”。假设您有两个并发下载,一个需要5秒,另一个需要7秒。你想答案是7(因为他们都在7秒内完成)?或者你想答案是12(因为他们都累计12秒完成)?

我假设您正在寻找,在这种情况下,7秒,然后您应该在发出所有请求之前设置startTime一次,然后只计算所有下载的时间完成。例如,您可以根据HTTPGetRequest中的任何计算而不是在totalElapsed进行任何计算,只需添加您自己的操作,该操作取决于您添加的所有其他操作,这将计算已用完的总数。在最后。或者,如果您希望经过的总时间仅反映您在下载过程中经过的总时间,那么只需设置{{1}}而不是递增它。

答案 2 :(得分:0)

另一种选择是注射&#34;火&#34;通过观察AFNetworkingOperationDidStartNotification通知,在操作的userInfo中显示日期。

//AFHTTPRequestOperation *operation = [...]
id __block observer = [[NSNotificationCenter defaultCenter] addObserverForName:AFNetworkingOperationDidStartNotification
        object:operation
         queue:nil
    usingBlock:^(NSNotification *note) {
                   operation.userInfo = @{@"fireDate": [NSDate date]};
                   [[NSNotificationCenter defaultCenter] removeObserver:observer];
              }];