加快将大量 JSON 数据写入磁盘的速度

Posted

技术标签:

【中文标题】加快将大量 JSON 数据写入磁盘的速度【英文标题】:Speed up writing a ton of JSON data to disk 【发布时间】:2014-04-15 15:50:34 【问题描述】:

我有一个大概有 40k 条记录的循环,基本上可以调用。似乎写入文件真的很慢。如果我迭代循环几乎是瞬间的,所以我意识到文件写入过程不是缓慢的核心数据迭代。有没有比我在这里做的更好的方法将数据流式传输到文件?

#ifndef jsonAppend
#define jsonAppend(X) [outStream write:[[X dataUsingEncoding:NSUTF8StringEncoding ] bytes] maxLength:[X lengthOfBytesUsingEncoding:NSUTF8StringEncoding]]
#endif



NSOutputStream *outStream = [NSOutputStream outputStreamToFileAtPath:tempFilePath append:NO];

    dispatch_async(backgroundQueue, ^

// Open an output stream to write to.
[outStream open];

// Other code ... blablabla

for (AHRSMessage *msg in results)


    @autoreleasepool
    

        [NSJSONSerialization writeJSONObject:msg.attributesAsDictionary toStream:outStream options:0 error:&error];
        jsonAppend(@",\n");

        i++;  // MessageCounter


        // Update UI only sometimes
        if (i % 100)
        

            dispatch_async(dispatch_get_main_queue(), ^
            
                @autoreleasepool 


                    float pct = i / recordCount ;
                    NSString *pctStr = [NSString stringWithFormat:@"%02.0f%%", pct * 100.0];
                    [[weakSelf percentLabel] setText:pctStr];
                    [[weakSelf parsingProgress] setProgress:pct animated:YES];

                    /* - Animate inner circle on units of 1% - */
                    int singPctMsgCount = recordCount / 100;
                    float fastParse = (i % singPctMsgCount) / (float)singPctMsgCount;
                    [[weakSelf fastParsingProgress] setProgress:fastParse animated:YES]     ;

                    [weakSelf updateUI];

                
            );

        

    
 // end for loop

);

【问题讨论】:

你写了多少个对象,每个对象有多大?你有什么理由不把它们写成一个 JSON 数组? 当我尝试拍摄时生成的文件大约为 18 兆,但我遇到了内存问题 - 比如 44k 个对象? 你意识到你可以(通过一些预防措施)在后台写入文件,对吧? 我发布的整个代码块都在 dispatch_async 后台线程中 那么每个对象大约是 500 字节? 【参考方案1】:

由于它只有 18MB,只需将其序列化为 NSMutableData 对象,然后将其写入磁盘。

这应该非常快。 NSMutableData 可以轻松处理甚至无法放入闪存(假设您有 64 位处理器)的数据量,更不用说 ios 设备上的 RAM。

像这样:

dispatch_async(backgroundQueue, ^

  NSMutableData *outData = [NSMutableData data];

  // Other code ... blablabla

  for (AHRSMessage *msg in results)
  

      @autoreleasepool
      
          [outData appendData:[NSJSONSerialization dataWithJSONObject:msg.attributesAsDictionary options:0 error:&error];

          i++;  // MessageCounter


          // Update UI only sometimes
          if (i % 100)
          

              dispatch_async(dispatch_get_main_queue(), ^
              
                  @autoreleasepool 

                      ... update progress bar ...

                  
              );

          

      
   // end for loop

  [outData writeToURL:outURL atomically:YES];
);

另外,我不会使用if (i % 100) 来决定是时候更新进度条了。相反,我会使用:

CFTimeInterval lastProgressUpdate = CACurrentMediaTime();

for (  ... ) 
  ...

  if (CACurrentMediaTime() - lastProgressUpdate > 0.02)  // 1/60th of a second. Which is the refresh rate of most LCD screens
    ... update progress bar ....

    lastProgressUpdate = CACurrentMediaTime()
  

【讨论】:

今天上班的时候试试这个!我有很大的希望! :) 感谢您的建议。

以上是关于加快将大量 JSON 数据写入磁盘的速度的主要内容,如果未能解决你的问题,请参考以下文章

为何Hbase的读取速度很快

MySQL 服务器的加快运行速度有哪些方法?

如何在显示大量文本时加快滚动响应速度

用 C++ 将 OpenCV 帧写入磁盘:单线程写入速度是不是受磁盘吞吐量以外的任何限制?

如何加快从磁盘加载XML文档的速度?

CPU缓存与内存屏障解析