更新
经过一些研究,我对我的代码做了一些改进。我首先将我测量时间的每个地方替换为:[NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];
替换为原子时间测量,例如:CFAbsoluteTimeGetCurrent();
我注意到这没有任何区别。与我们的服务器人员核对后,我注意到服务器显示了令人印象深刻的结果——这让我认为这里的瓶颈不是服务器,而是我的笔记本电脑/其他一些阻碍。
原帖
我正在尝试对我的服务器进行负载测试,因此我构建了一个模拟应用中用户流的场景。此流程包含对服务器的大约 11-17 次调用,其中一些必须是同步的(因为用户将无法到达某个屏幕,除非他通过其他屏幕)。
然后我同时使用 X
线程运行这个场景,试图对服务器施加压力并查看最薄弱的环节在哪里。为了分析信息,每次响应返回(成功或失败)时,我都会将一些相关信息记录到文件中,并注意到每次调用的时间都发生了一些非常奇怪的事情。
为了测量通话时间,我使用以下方法测量了每次通话的开始时间:
test.startTime = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];
//fire the request
[operation start];
成功/失败 block 中发生的第一件事是:
成功
void (^successWrapper) (AFHTTPRequestOperation *, id) = ^(AFHTTPRequestOperation *operation, id responseObject){
//#################TEST ANALYTICS###############
NSDate *endTime = [NSDate date];
test.endTime = [NSNumber numberWithDouble:[endTime timeIntervalSince1970]];
test.lat = [NSNumber numberWithDouble:(test.endTime.doubleValue - test.startTime.doubleValue)];
//##############################################
//Some other success stuff...
};
失败:
void (^failureWrapper) (AFHTTPRequestOperation *, NSError *) = ^(AFHTTPRequestOperation *operation, NSError *error) {
//#################TEST ANALYTICS###############
NSDate *endTime = [NSDate date];
test.endTime = [NSNumber numberWithDouble:[endTime timeIntervalSince1970]];
test.lat = [NSNumber numberWithDouble:(test.endTime.doubleValue - test.startTime.doubleValue)];
//##############################################
//Some other failure stuff...
};
然而,我在日志文件中遇到了非常高的延迟,而且随着 X
越来越大,情况变得更糟。
我假设问题是由于线程之间的上下文切换引起的,但我不确定。所以我的问题是:如何在多线程系统中正确测量AFNetworking
中每次调用的响应时间?
一些注意事项:
- 如上所述,一些调用可以同时发生,而另一些则必须按顺序发生。
X
最终应该非常高 (>10000)。
谢谢!
最佳答案
可以并发运行的 NSURLConnection
网络请求数量有限。您可以启动任意数量的操作,但 NSURLConnection
只会同时运行有限数量的操作(我相信是 4-6,具体取决于操作系统版本)。随后的 NSURLConnection
请求将等待前面的请求完成。在极端情况下(例如提交数百个请求),这甚至会导致后面的请求超时(除非您指定足够大的超时参数)。此约束不是网络延迟之一,而是操作系统对客户端施加的并发请求数量有限的产物。
在客户端应用程序中,当使用基于 NSOperationQueue
的框架(如 AFNetworking)时,您可以通过不自己启动操作来处理此限制,而只是将它们添加到 NSOperationQueue
。然后,您可以将操作队列的 maxConcurrentOperationCount
限制为某个合理的数字,该数字对应于可以在任何给定时间运行的并发 NSURLConnection
请求的数量(例如,我可能建议 5)在单个操作中消除这种延迟现象。如果您要将这些请求添加到自己的队列中,则需要为该队列指定 maxConcurrentOperationCount
。如果您正在使用 AFHTTPRequstOperationManager
,您将在管理器的 operationQueue
属性上执行此操作。
如果您想在上述上下文中对 AFNetworking 的性能进行基准测试,问题是您是否要测量总耗时(在这种情况下,您可以在将其添加到队列时捕获开始时间,然后计算完成 block 中耗时,类似于您在问题中概述的方式)或者您是否希望捕获实际运行操作所花费的时间。
如果您对后者感兴趣,您确实希望在操作队列导致 start
方法被调用时启动计时器,您可以为 添加观察者AFNetworkingOperationDidStartNotification
和 AFNetworkingOperationDidFinishNotification
通知,或者只是 fork AFNetworking 并修改 AFURLConnectionOperation
来为您计算耗时。
最后,有点不清楚您的问题是真的对应用程序进行压力测试,还是对服务器进行压力测试。如果只是对应用程序进行压力测试,上面的方法应该有效。如果您想对服务器进行压力测试以模拟许多并发用户,那将更加困难,并且可能需要完全绕过 NSURLConnection
/AFNetworking(使用 CFNetwork
概述 here )或者真正设置一组物理设备/计算机并让它们同时进行客户端 AFNetworking 压力测试。
关于objective-c - 在多线程应用程序的 AFNetworking 中测量响应时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24785665/