我循环遍历由核心数据谓词检索的文件路径数组,每次迭代循环时压缩和上传每个文件,总共约4或5000个文件。 (我用于压缩的技术基本上是这里描述的技术:Best way to loop through a lot of files and zip each one separately?)目前,我正在从Xcode以调试模式运行应用程序。片刻之后,随着循环的每次迭代,应用程序似乎运行速度变慢,Xcode也会这样做 - 实际上,我的整个计算机的响应速度都会降低。我现在正在研究涉及NSStrings,NSArrays,NSNotifications等的有效循环的一般规则,但我也希望有人也可以指出代码中明显的瓶颈和低效率。虽然我的代码使用了垃圾收集,但我尝试使用可能有所作为的小希望来发布调用,尽管我的理解是它不应该。这是我的代码的简略版本,只包含重要部分:
//Zip paths saved in Core Data and upload them to a server
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
//get path of the shell script that zips a file
NSString *zipShellScript = [[NSBundle mainBundle] pathForResource:@"backupzipper"
ofType:@"sh"];
//get array of File managed objects related to User managed object
NSArray *filesToUpload = [User files];
//args for the shell script
//NSString *sourceFilePath = [NSString string];
//NSString *targetFilename = [NSString string];
//NSString *targetFilePath = [NSString string];
//the following appears to make a big improvement
NSString *sourceFilePath = [[NSString alloc] initWithString:[NSString string]];
NSString *targetFileName = [[NSString alloc] initWithString:[NSString string]];
NSString *targetFilePath = [[NSString alloc] initWithString:[NSString string]];
NSError *error;
for (File *file in filesToUpload) //loop through array of File managed objects
{
NSTask *task = [[NSTask alloc] init];
sourceFilePath = file.path;
targetFilename = [NSString stringWithFormat:@"%@.zip",
[[sourceFilePath lastPathComponent]
stringByDeletingPathExtension]]; //e.g. misc.doc will produce misc.zip
[task setArguemnts:[NSArray arrayWithObjects:zipShellScript,
sourceFilePath, //full path of file to zip e.g. /Users/stifin/documents/misc.doc
workingDirectory, //where the zip will be placed e.g. /Users/stifin/Library/Application Support/MyApp/
targetFilename, //filename after zipping e.g. misc.zip
nil]];
[sourceFilePath release]; //my attempt to reduce memory usage even though this is garbage collected app
[targetFilename release];
[task setLaunchPath@"/bin/sh"];
[task setStandardInput:[NSPipe pipe]]; //fixes odd behaviour where NSLog no longer works after NSTask
//do zip
[task launch];
[task waitUntilExit];
if ([task terminationReason] == NSTaskTerminationReasonExit)
{
[task release]; //doubt this helps
[self uploadFile:targetFilePath]; //method just sleeps for 1 sec to simulate upload time
file.dateUploaded = [NSDate date];
error = nil;
if ([context save:&error])
NSLog(@"Saved ok");
else
NSLog(@"Save error: %@", [error localizedDescription]);
//delete zip from working directory
[self cleanUpFile:targetFilePath];
[targetFilePath release]; //doubt this helps
//send notification of file processed
info = [NSDictionary dictionaryWithObjectsAndKeys:
file.filename, @"name",
file.sizeBytes, @"size",
[NSNumber numberWithBool:YES], @"success",
nil];
[nc postnNotificationName:@"FileProcessed" object:nil userInfo:info];
[info release]; //doubt this helps
}
else {
//handle task failure
}
}
[nc removeObserver:self];
答案 0 :(得分:1)
如documentation所述,-release被忽略。如果您想立即收集,请使用[[NSGarbageCollector defaultCollector] collectIfNeeded];
或甚至-collectExhaustively
。不要每次通过循环,每隔一百左右就这样做。
当然,所有这些都假设您已经使用过仪器来确保这是问题所在。你还没有说过你是否已经这样做了,这让我相信你在做出假设。问题可能只是在其他地方(虽然我同意这是迄今为止最有可能的候选人 - GC +在紧密循环中的许多分配需要一些额外的关注)。工作不是一个好方法。先测量,然后优化。
答案 1 :(得分:0)
如果你真的想加快速度,可以为每个CPU内核创建1个线程并将列表分开。在任何现代CPU上,这将使拉链速度提高4-8倍!
如果您的文件很小,它也会大大提高上传速度,因为花费大量时间来管理连接而不是实际发送数据。
对于较大的文件(超过几百Kb)或甚至1个CPU核心,由于某些服务器限制每个连接带宽,因此至少同时进行2次上传仍然很有用,并且它将允许使用完整的上载带宽(总是上传而不是等待压缩或连接完成)。