我正在循環由核心數據謂詞檢索的文件路徑數組,每循環迭代一次壓縮和上傳每個文件,總共大約有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 [email protected]"/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];
我發現這個建議[「避免autorelease」](http://www.mulle-kybernetik.com/artikel/Optimization/opti-5.html)。我沒有想到應用於GC環境,但我相應地改變了shell腳本的參數(在上面編輯的代碼中),並且對於顯着的改進感到驚訝。 – stifin
只要你明白它在做什麼,autorelease沒什麼問題。我會說「避免在緊密循環中使用自動釋放或使用自己的本地池,每隔一段時間排空它」會更重要。 –