我正在將大文件複製操作從NSStream
轉換爲使用GCD的調度IO實現。使用GCD的大文件複製 - 調度IO消耗大量內存
將兩個1GB文件一起復制到一個2GB文件中時,該應用程序在使用GCD時消耗2GB內存。 NSStream
實現只消耗50MB。
在儀器中,我可以看到start_wqthread
調用分配1MB塊,正如我請求的塊大小爲調度IO高位標記,但不是在寫入輸出流後被釋放,而是掛起。
如何在緩衝區寫入輸出流之後釋放緩衝區?
如果我在Xcode中創建一個全新的OS X Cocoa應用程序,並將以下代碼粘貼到applicationDidFinishLaunching:
方法中,它將消耗500-2000MB的內存。 (要進行測試,請將臨時文件引用替換爲本地文件引用。)
使用OS 10.9 SDK以OS 10.9爲目標創建新項目時,ARC禁止對dispatch_release()
的調用。在舊項目中定位OS 10.6時,即使啓用ARC,也允許調用dispatch_release()
,但不影響內存佔用。
NSArray* files = @[@"/1GBFile.tmp", @"/1GBFile2.tmp"];
NSString* outFile = @"/outFile.tmp";
NSString* queueName = [NSString stringWithFormat:@"%@.IO", [[NSBundle mainBundle].infoDictionary objectForKey:(id)kCFBundleIdentifierKey]];
dispatch_queue_t queue = dispatch_queue_create(queueName.UTF8String, DISPATCH_QUEUE_SERIAL);
dispatch_io_t io_write = dispatch_io_create_with_path(DISPATCH_IO_STREAM, outFile.UTF8String, (O_RDWR | O_CREAT | O_APPEND), (S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH), queue, NULL);
dispatch_io_set_high_water(io_write, 1024*1024);
[files enumerateObjectsUsingBlock:^(NSString* file, NSUInteger idx, BOOL *stop) {
dispatch_io_t io_read = dispatch_io_create_with_path(DISPATCH_IO_STREAM, file.UTF8String, O_RDONLY, 0, queue, NULL);
dispatch_io_set_high_water(io_read, 1024*1024);
dispatch_io_read(io_read, 0, SIZE_MAX, queue, ^(bool done, dispatch_data_t data, int error) {
if (error) {
dispatch_io_close(io_write, 0);
return;
}
if (data) {
size_t bytesRead = dispatch_data_get_size(data);
if (bytesRead > 0) {
dispatch_io_write(io_write, 0, data, queue, ^(bool doneWriting, dispatch_data_t dataToBeWritten, int errorWriting) {
if (errorWriting) {
dispatch_io_close(io_read, DISPATCH_IO_STOP);
}
});
}
}
if (done) {
dispatch_io_close(io_read, 0);
if (files.count == (idx+1)) {
dispatch_io_close(io_write, 0);
}
}
});
}];
我也在考慮順序文件操作可能會更好。我沒有測試過最新的代碼,雖然時間大致相同?我很高興你找到了解決辦法;因爲這是一個很好的例子,我已經提出了你的問題和答案。 - 最好的祝福 :) –