objective-c - 在多线程应用程序的 AFNetworking 中测量响应时间

标签 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];

成功/失败 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 方法被调用时启动计时器,您可以为 添加观察者AFNetworkingOperationDidStartNotificationAFNetworkingOperationDidFinishNotification 通知,或者只是 fork AFNetworking 并修改 AFURLConnectionOperation 来为您计算耗时。

最后,有点不清楚您的问题是真的对应用程序进行压力测试,还是对服务器进行压力测试。如果只是对应用程序进行压力测试,上面的方法应该有效。如果您想对服务器进行压力测试以模拟许多并发用户,那将更加困难,并且可能需要完全绕过 NSURLConnection/AFNetworking(使用 CFNetwork 概述 here )或者真正设置一组物理设备/计算机并让它们同时进行客户端 AFNetworking 压力测试。

关于objective-c - 在多线程应用程序的 AFNetworking 中测量响应时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24785665/

相关文章:

ios - 使用 AFNetworking 下载多个文件时出现内存压力问题

ios - 将 BOOL 类型的默认值设置为 YES

ios - OpenGL ES iOS 属性问题

iphone - 应用程序在模拟器上运行良好,但在设备上崩溃

ios - iOS 下 altBeacons 上的 Major 和 Minor

java - hadoop中的 transient 变量和静态方法,dev求教

c# - 多线程 - 5 或 100 个线程?

Python 线程与 Linux 中的多处理

ios - AFHTTPSessionManager 子类 : Post API with body.

ios - 应用程序进入后台后未调用 AFNetworking 成功/失败 block