测量多线程应用上AFNetworking的响应时间

时间:2014-07-16 16:13:18

标签: objective-c multithreading afnetworking load-testing

更新

经过一些研究,我对我的代码做了一些改进。我首先使用:[NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];替换我测量时间的每个地方,并使用原子时间测量,例如:CFAbsoluteTimeGetCurrent();

我注意到没有任何区别。检查我们的服务器人我注意到服务器显示了令人印象深刻的结果 - 这让我觉得这里的瓶颈不是服务器而是我的笔记本电脑/其他一些方面。


原帖

我正在尝试加载测试我的服务器,因此我构建了一个模拟应用程序中用户流的方案。此流程包含对服务器的大约11-17个调用,其中一些必须是同步的(因为除非用户通过其他屏幕,否则无法访问某个屏幕)。

然后我同时使用X个线程运行这个场景,试图强调服务器并查看最弱链接的位置。为了分析信息,我每次回复时都会将一些相关信息记录到一个文件中(无论是成功还是失败),并注意到每个调用的时间正在发生一些非常奇怪的事情。

为了测量通话时间,我使用以下方法测量每次通话的开始时间:

 test.startTime = [NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]];
//fire the request
[operation start];

成功/失败块中发生的第一件事是:

成功

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)。

谢谢!

1 个答案:

答案 0 :(得分:3)

可以并发运行的NSURLConnection个网络请求数量有限。你可以开始许多你想要的操作,但是NSURLConnection只能同时运行一个有限的数量(4-6,我相信,这取决于操作系统版本)。随后的NSURLConnection请求将等待先前的请求完成。在极端情况下(例如,提交数百个请求),这甚至可能导致后面的请求超时(除非您指定足够大的超时参数)。此约束不是网络延迟之一,而是操作系统在客户端上施加的有限数量的并发请求的工件。

在客户端应用程序中,当使用基于NSOperationQueue的框架(如AFNetworking)时,您可以通过不自行启动操作来处理此限制,而只是将它们添加到NSOperationQueue。然后,您可以将操作队列的maxConcurrentOperationCount约束到某个合理的数字,该数字对应于可以在任何给定时间运行的并发NSURLConnection请求数(例如,我可能建议5)以消除此在各个操作中出现延迟。如果您要将这些请求添加到自己的队列中,则需要为该队列指定maxConcurrentOperationCount。如果您正在使用AFHTTPRequstOperationManager,则必须在经理的operationQueue财产上执行此操作。

如果您想在上述环境中对AFNetworking的性能进行基准测试,那么问题是您是否希望测量总耗用时间(在这种情况下,您可以在将其添加到队列时捕获开始时间)然后计算完成块中的已用时间,类似于您在问题中列出的方式),或者您是否希望捕获实际运行操作所花费的时间。

如果你对后者感兴趣,你真的想在操作队列导致调用start方法时启动计时器,你可以为{{1}添加观察者}和AFNetworkingOperationDidStartNotification通知,或只是分叉AFNetworking并修改AFNetworkingOperationDidFinishNotification来计算您的经过时间。

最后,关于您的问题是否真的是对应用程序进行压力测试,或者对服务器进行压力测试,还不清楚。如果只是对应用程序进行压力测试,则上述应该可行。如果您想对服务器进行压力测试以模拟许多同时发生的用户,那就更难了,可能需要完全绕过AFURLConnectionOperation / AFNetworking(NSURLConnection概述here)或者真正建立一系列物理设备/计算机,让他们同时进行客户端AFNetworking压力测试。