加快将大量 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 数据写入磁盘的速度的主要内容,如果未能解决你的问题,请参考以下文章