草庐IT

ios - 解析查询花费的时间太长

coder 2024-01-30 原文

我必须提高连接到 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>

另外,“event”表有超过 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 我不确定这是否重要,但“事件”表中的一个字段是 PFFile(图像)。这会使查找查询变慢吗?

最佳答案

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

  1. 不要连续运行初始下载
  2. 不要在循环中调用 PFInstallation *currentInstallation = [PFInstallation currentInstallation]; & [currentInstallation saveInBackground];
  3. 不要在循环中连续下载每个图像 UIImage *image = [UIImage imageWithData:[userImageFile getData]];

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

关于ios - 解析查询花费的时间太长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36327996/

有关ios - 解析查询花费的时间太长的更多相关文章

  1. Ruby 解析字符串 - 2

    我有一个字符串input="maybe(thisis|thatwas)some((nice|ugly)(day|night)|(strange(weather|time)))"Ruby中解析该字符串的最佳方法是什么?我的意思是脚本应该能够像这样构建句子:maybethisissomeuglynightmaybethatwassomenicenightmaybethiswassomestrangetime等等,你明白了......我应该一个字符一个字符地读取字符串并构建一个带有堆栈的状态机来存储括号值以供以后计算,还是有更好的方法?也许为此目的准备了一个开箱即用的库?

  2. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. ruby - 用逗号、双引号和编码解析 csv - 2

    我正在使用ruby​​1.9解析以下带有MacRoman字符的csv文件#encoding:ISO-8859-1#csv_parse.csvName,main-dialogue"Marceu","Giveittohimóhe,hiswife."我做了以下解析。require'csv'input_string=File.read("../csv_parse.rb").force_encoding("ISO-8859-1").encode("UTF-8")#=>"Name,main-dialogue\r\n\"Marceu\",\"Giveittohim\x97he,hiswife.\"\

  5. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  6. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  7. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  8. ruby-on-rails - 将 Ruby 中的日期/时间格式化为 YYYY-MM-DD HH :MM:SS - 2

    这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build

  9. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  10. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

随机推荐