我正在尝试使用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++;
}
答案 0 :(得分:7)
答案 1 :(得分:4)
在计算累积时间(非经过时间)方面,我刚刚创建了一个AFHTTPRequestOperation
的子类来捕获开始时间。否则,您将无法准确知道它何时开始:
@interface TimedAFHTTPRequestOperation : AFHTTPRequestOperation
@property (nonatomic) CFAbsoluteTime startTime;
@end
@implementation TimedAFHTTPRequestOperation
- (void)start
{
self.startTime = CFAbsoluteTimeGetCurrent();
[super start];
}
@end
(注意我使用CFAbsoluteTimeGetCurrent
与CACurrentMediaTime
;使用您想要的任何内容,但只是保持一致。)
然后在执行下载的代码中,您可以使用此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];
}];