在AFNetworking HTTP GET中测量响应时间 [英] Measuring response time in AFNetworking HTTP GET
问题描述
使用AFNetworking下载文件时,我正在尝试测量每个GET请求所花费的时间。我反复循环下载文件。
我遇到的问题是我测量总时间的方式,它提供的总时间比实际多得多。例如,对于50次下载,它给出了72秒,但实际上仅花费了大约5秒。我还怀疑5秒对于50次下载来说太低了(每个文件的下载大小为581 kb)。
I am trying to measure time taken per GET request when downloading a file using AFNetworking. I am downloading a file repeatedly in a loop. The problem I am having is that the way I am measuring total time, it gives a much larger total time than it actually is. For example, for 50 downloads it gives 72 sec but in reality it only took around 5 sec. I also suspect 5 sec is too low for 50 downloads(the download size is 581 kb per file).
在这种情况下,如何有效地测量时间?从发出请求到收到响应,我需要时间。
How do I effectively measure time in this case? I need time from the moment request is fired till response in received.
我下载文件的方法:
- (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:
I am creating a NSOperationQueue in my viewDidLoad:
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方法:
I am invoking the HTTPGetRequest method as follows:
- (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++;
}
推荐答案
在计算累计时间(而不是经过时间)时,我刚刚创建了一个 AFHTTPRequestOperation
子类来捕获开始时间。否则,您将无法确切知道它的开始时间:
In terms of calculating cumulative time (not elapsed time), I have just created a subclass of AFHTTPRequestOperation
that captures the start time. Otherwise, you won't know precisely when it started:
@interface TimedAFHTTPRequestOperation : AFHTTPRequestOperation
@property (nonatomic) CFAbsoluteTime startTime;
@end
@implementation TimedAFHTTPRequestOperation
- (void)start
{
self.startTime = CFAbsoluteTimeGetCurrent();
[super start];
}
@end
(请注意,我正在使用 CFAbsoluteTimeGetCurrent
与 CACurrentMediaTime
;使用您想要的任何内容,但要保持一致。)
(Note I'm using CFAbsoluteTimeGetCurrent
versus CACurrentMediaTime
; use whatever you want, but just be consistent.)
然后在进行下载的代码中,可以使用此 TimedAFHTTPRequestOperation
代替 AFHTTPRequestOperation
:
Then in the code that's doing the downloads, you can use this TimedAFHTTPRequestOperation
instead of AFHTTPRequestOperation
:
TimedAFHTTPRequestOperation *operation = [[TimedAFHTTPRequestOperation alloc] initWithRequest:request];
该代码的完成块可以使用 startTime
TimedAFHTTPRequestOperation 的>属性,以计算给定操作经过的时间并将其添加到总时间中:
That code's completion block can then use the startTime
property of TimedAFHTTPRequestOperation
to calculate the time elapsed for the given operation and add it to the total time:
[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
。
That's how you calculate the elapsedTime
and append them together to calculate the totalTime
.
关于如何知道何时完成操作,我会
In terms of how to know when the operations are done, I would
-
修改
HTTPGetRequest
以返回NSOperation
;
具有 startDownload
创建完成操作,然后添加所有这些操作作为依赖项的操作:
have startDownload
create a completion operation and then add all of these operations as dependencies:
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];
这实现了几个目标,即创建完成操作,计算总时间(而不是经过的总时间)。
That achieves several goals, namely creating a completion operation, calculating the total time (as opposed to the total time elapsed).
顺便说一句,我也建议取消创建您的
。您可能应该只为每个应用创建一个。如果您曾经开始使用 HTTPGetRequest
中的AFHTTPClient enqueueHTTPRequestOperation
而不是创建自己的操作队列,这一点尤其重要。我也认为不需要调用 registerHTTPOperationClass
。
By the way, I'd also suggest pulling the creation of AFHTTPClient
out of your HTTPGetRequest
. You should probably only create one per app. This is especially important in case you ever started using enqueueHTTPRequestOperation
instead of creating your own operation queue. I also see no need for your call to registerHTTPOperationClass
.
您将 totalElapsed
增加了 lapsedTime
,但 elapsedTime
是从 startTime
计算,它本身代表作业第一次排队的时间,而不是实际开始下载的时间。请记住, HTTPGetRequest
几乎立即返回(已设置 elapsedTime
)。因此,如果您要排队5次下载, HTTPGetRequest
会运行5次(并设置并重置 startTime $ c $),我不会感到惊讶。 c>五次)甚至在第一个请求启动之前。
You are incrementing the totalElapsed
by elapsedTime
, but elapsedTime
is calculated from startTime
, which itself represents the time that the jobs were first queued, not when the download actually started. Remember that HTTPGetRequest
returns almost immediately (having set elapsedTime
). Thus if you're queueing five downloads, I wouldn't be surprised that HTTPGetRequest
runs five times (and sets and resets startTime
five times) before the first request even is initiated.
问题是,您是否正在进行并发下载,如果这样,那么会进一步使问题复杂化然后,您的意思是已用完。假设您有两次并发下载,一次下载需要5秒钟,另一次需要7秒钟。您是否希望答案为7(因为它们都在7秒内完成)?还是您希望答案是12(因为它们都在12秒钟内完成)?
The question is further complicated by the question of whether you're doing concurrent downloads, and if so, what you then mean by "total elapsed". Let's say you have two concurrent downloads, one that takes 5 seconds, another takes 7 seconds. Do you want the answer to be 7 (because they both finished in 7 seconds)? Or do you want the answer to be 12 (because they both finished in a cumulative 12 seconds)?
在这种情况下,我假设您正在寻找,即7秒,那么您应该在启动所有请求之前设置一次 startTime
,然后仅计算何时完成所有下载。例如,您可以根本不用在 HTTPGetRequest
中进行任何计算,而只是添加自己的操作,该操作取决于您添加的所有其他操作,从而计算出总耗用的时间。在最后。或者,如果您希望总经过时间仅反映下载过程中的总经过时间,则只需设置 totalElapsed
而不是增加它。
I'm presuming that you're looking for, in this scenario, 7 seconds, then you should set the startTime
once before you initiate all of your requests, and then only calculate when all of the downloads are done. You could, for example, rather than doing any calculations in HTTPGetRequest
at all, just add your own operation that is dependent upon all the other operations you added, which calculates the total elapsed. at the very end. Or, if you want the the total elapsed to just reflect the total elapsed while you're in the process of downloading, then just set totalElapsed
rather than incrementing it.
这篇关于在AFNetworking HTTP GET中测量响应时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!