0

我正在尝试测量使用 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++;

    }
4

3 回答 3

7

使用AFHTTPRequestOperationLogger

于 2013-05-23T16:51:39.890 回答
4

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

@interface TimedAFHTTPRequestOperation : AFHTTPRequestOperation

@property (nonatomic) CFAbsoluteTime startTime;

@end

@implementation TimedAFHTTPRequestOperation

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

    [super start];
}

@end

(注意我使用CFAbsoluteTimeGetCurrentvs CACurrentMediaTime; 使用你想要的任何东西,但要保持一致。)

然后在进行下载的代码中,您可以使用它TimedAFHTTPRequestOperation来代替AFHTTPRequestOperation

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

然后,该代码的完成块可以使用 的startTime属性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.


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

问题是您是否正在进行并发下载,如果是,那么您所说的“总经过时间”是什么意思,这个问题变得更加复杂。假设您有两个并发下载,一个需要 5 秒,另一个需要 7 秒。你希望答案是 7(因为他们都在 7 秒内完成)?还是您希望答案为 12(因为他们都在累积 12 秒内完成)?

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

于 2013-05-11T14:52:08.783 回答
0

另一种选择是通过观察 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];
              }];
于 2014-05-04T13:50:21.077 回答