解析查询耗时太长

时间:2016-03-31 08:27:08

标签: ios objective-c parse-platform

我必须提高连接到Parse的iOS应用的性能。到目前为止,我已经检查过一些findObject查询需要太长时间,有些甚至是10秒!

我会把最坏情况之一的代码和迄今为止我尝试过的代码放在一起:

+ (void) getAllEvents
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    PFQuery *timestampsQuery = [PFQuery queryWithClassName:@"TimeStamp"];
    [timestampsQuery fromLocalDatastore];
    [timestampsQuery whereKey:@"type" equalTo:@"event"];
    // This query very often (not always) takes a couple of seconds
    NSArray *timeStampObjects = [timestampsQuery findObjects];
    NSArray *timeStamps = [self TransformPFObjectIntoTimeStamp:timeStampObjects];

    PFQuery *query = [PFQuery queryWithClassName:@"Event"];
    if ([self noNetworkConnection])
    {
        [query fromLocalDatastore];
    }
    else
    {
        [query whereKey:@"user" equalTo:[PFUser currentUser]];
    }
    [query includeKey:@"admin"];
    // This query very often (not always) takes several seconds, 6, 7…even 10 seconds!
    NSArray *objects = [query findObjects];        
    NSMutableArray *eventArray = [NSMutableArray arrayWithArray:[self TransformPFObjectIntoEvents:objects]];

    NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:eventArray,@"events",timeStamps,@"timestamps", nil];
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:GET_ALL_MY_EVENTS object:dict];
    });

  });
}

+ (NSArray *)TransformPFObjectIntoTimeStamp:(NSArray *)objects 
{
   NSMutableArray* timestamps = [[NSMutableArray alloc]init];
   for (PFObject* object in objects) 
   {
      TimeStamp* timeStamp = [[TimeStamp alloc] init];
      timeStamp.parseObject = object;
      [timestamps addObject:timeStamp];
   }
   return timestamps;
}

+ (NSMutableArray *)TransformPFObjectIntoEvents:(NSArray *)objects 
{
   [PFObject pinAllInBackground:objects withName:PFObjectDefaultPin];
   NSMutableArray* eventArray = [[NSMutableArray alloc]init];
   for (PFObject* object in objects) 
   {
      Event* event = [[Event alloc] init];
      event.parseObject = object;
      PFInstallation *currentInstallation = [PFInstallation currentInstallation];
      [currentInstallation addUniqueObject:object[@"channel"] forKey:@"channels"];
      [currentInstallation saveInBackground];
      if(event.parseObject[@"imageFile"] != [NSNull null])
      {
        PFFile *userImageFile = event.parseObject[@"imageFile"];
        if (userImageFile != NULL)
        {
            UIImage *image = [UIImage imageWithData:[userImageFile getData]];
            [event setAttributeImage:image];
        }
      }
      [eventArray addObject:event];
   }
   return eventArray;
}

我必须补充说,对findObjects的第二次调用有时会给我一个“cfnetwork sslhandshake failed(-9824)”,这对我来说很奇怪,因为应用程序的info.plist包含这些键(但我想这应该是另一个问题):

<key>NSTemporaryExceptionRequiresForwardSecrecy</key> 
<false/>
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>

另外,表“事件”有超过1000个寄存器。

我尝试了什么:

1)注释[timestampsQuery fromLocalDatastore]; 相同的结果,这些查询需要太长时间。

2)用户findObjectInBackground:

+ (void) getAllMyEvents{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    _calls = 0;
    PFQuery *timestampsQuery = [PFQuery queryWithClassName:@"TimeStamp"];
    [timestampsQuery fromLocalDatastore];
    [timestampsQuery whereKey:@"type" equalTo:@"event"];
    [timestampsQuery findObjectsInBackgroundWithBlock:^(NSArray * _Nullable objects, NSError * _Nullable error) {
        [self completeQueriesWithType:1 andObjects:objects];
    }];

    PFQuery *query = [PFQuery queryWithClassName:@"Event"];
    if ([self noNetworkConnection])
    {
        [query fromLocalDatastore];
    }
    else
    {
        [query whereKey:@"user" equalTo:[PFUser currentUser]];
    }
    [query includeKey:@"admin"];
    [query findObjectsInBackgroundWithBlock:^(NSArray * _Nullable objects, NSError * _Nullable error) {
        [self completeQueriesWithType:2 andObjects:objects];
    }] ;
 });
}

+ (void) completeQueriesWithType:(int)type andObjects:(NSArray *)objs
{
    _calls++;
    NSArray *timeStamps = nil;
    NSMutableArray *eventArray = nil;
    if(type == 1)
    {
       timeStamps = [TimeStamp TransformPFObjectIntoTimeStamp:objs];
    }
    else if(type == 2)
    {
        eventArray = [NSMutableArray arrayWithArray:[self TransformPFObjectIntoEvents:objs]];
    }
    if(_calls == 2)
    {
       NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:eventArray,@"events",timeStamps,@"timestamps", nil];
       dispatch_async(dispatch_get_main_queue(), ^{
           [[NSNotificationCenter defaultCenter] postNotificationName:GET_ALL_MY_EVENTS object:dict];
       });
    }
}

但它仍然需要几秒钟而且我也遇到了这个错误:“警告:正在主线程上执行长时间运行的操作。  打破warnBlockingOperationOnMainThread()进行调试。“为什么?如果我在后台运行它。

因为我知道Parse本地数据库对性能有一些影响我虽然根本没有使用它,但是删除它的所有外观,但我想用Parse本地数据库修复它,如果可能的话。

那么......为什么这些查询花了这么多时间?

修改 按照@Wain的建议,我已经完成了这个测试:

+ (void) getAllEvents
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    NSLog(@"Running only second of findObjects");
    PFQuery *query = [PFQuery queryWithClassName:@"Event"];
    if ([self noNetworkConnection])
    {
        NSLog(@"Reading from local datastore");
        [query fromLocalDatastore];
    }
    else
    {
        [query whereKey:@"user" equalTo:[PFUser currentUser]];
    }
    [query includeKey:@"admin"];
    // This query very often (not always) takes several seconds, 6, 7…even 10 seconds!
    NSLog(@"Just before findObjects");
    NSArray *objects = [query findObjects];        
    NSLog(@"End of running only second of findObjects");
  });
}

有了这些结果:

2016-03-31 11:15:29.295 MyApp[...] Running only second of findObjects
2016-03-31 11:15:29.318 MyApp[...] Just before findObjects
2016-03-31 11:15:38.025 MyApp[...] End of running only second of findObjects

只有这个方法NSArray * objects = [query findObjects];需要9秒!

编辑2 我不确定这是否重要,但是&#34;事件中的一个字段&#34; table是PFFile(图像)。这会使查询查询变慢吗?

1 个答案:

答案 0 :(得分:0)

您可以更改许多内容,但是您应该使用工具来查看实际花费最多时间的内容。需要考虑的事项:

  1. 不要连续运行初始下载
  2. 请勿致电PFInstallation *currentInstallation = [PFInstallation currentInstallation];&amp;循环中的[currentInstallation saveInBackground];
  3. 请勿以循环UIImage *image = [UIImage imageWithData:[userImageFile getData]];
  4. 连续下载每张图片

    您正在将初始下载视为罪魁祸首,但更有可能是您的后续处理,您将开始大量的安装保存和同步图像下载......