iOS 使用Instruments優化內存性能ios
項目中使用到圖片合成視頻,發現內存增加十分的迅速,致使一些由於內存引發的問題,本文使用這個案例,結合Instruments工具檢測和分析問題,最終解決內存問題。git
本文的Demo代碼 ScreenRecorderTest2app
查看某個範圍內的內存增加ide
函數
堆內存分配的詳細統計數據
點擊All Heap Allocations旁邊的小箭頭按鈕能夠看堆內存分配的詳細統計數據: 工具
統計數據表中能夠看出AppleJPEG 庫調用 applejpeg_decode_create 方法建立了不少的內存的數據
右邊區域顯示的是函數的調用棧信息面板(Stack Trace),右上角的工字型按鈕能夠切換顯示系統函數調用
性能
內存分配大小與對應的代碼調用信息的可視化顯示
點擊調用棧中的高亮代碼能夠查看代碼詳情和內存信息:
優化
右邊的標註區域顯示的是內存佔用的比例。code
上圖中看到buffer對象和image佔用的內存最大,可是buffer在每次使用以後都會調用CVPixelBufferRelease釋放對應的內存,不會有內存的問題,image對象釋放的不及時,會在整個while循環塊中保留一段時間,致使內存的增加。
此外image對象釋放不及時和在在同一時間調用CVPixelBufferRelease(buffer);釋放buffer也有關係,若是沒有建立buffer和釋放buffer的操做,image對象的增加也不會很明顯,釋放的速度也挺快,下面兩個對照組能夠進行對比分析視頻
對照組1:只有在循環中建立image對象內存增加:
內存增加爲2.73M

對照組2:在循環中添加autoreleasepool建立image對象內存增加:
內存增加爲492K

由上可知,使用autoreleasepool能夠有效的解決在某個循環中建立大量的內存敏感型對象致使的內存上漲的問題
最終解決方案
在while循環內部使用autoreleasepool塊,每次循環arc對象得以及時的釋放,內存增加從原來的16.81M降低到了只有475K

代碼:
while(i < imageNames.count) { // 添加自動釋放池,讓內存敏感型的對象(UIImage)及時釋放 @autoreleasepool { // 代碼省略... NSString *imageName = [imageNames objectAtIndex:i]; NSString* imagePath = [imageSavedDir stringByAppendingPathComponent:imageName]; UIImage* image = [UIImage imageWithContentsOfFile:imagePath]; if(adaptor.assetWriterInput.readyForMoreMediaData) { i++; CMTime frameTime = CMTimeMake(1, fps); CMTime lastTime = CMTimeMake(i, fps); CMTime presentTime = CMTimeAdd(lastTime, frameTime); buffer = [self pixelBufferFromCGImage:[image CGImage] size:videoFrameSize]; // 寫入視頻 BOOL result = [adaptor appendPixelBuffer:buffer withPresentationTime:presentTime]; if(buffer) { CVPixelBufferRelease(buffer); } // 代碼省略... [NSThread sleepForTimeInterval:0.05]; } else { NSLog(@"Error: Adaptor is not ready"); [NSThread sleepForTimeInterval:0.05]; i--; } } }
以上是使用Instruments解決內存問題的總結,若有不妥之處還請不吝賜教
本文的Demo代碼 ScreenRecorderTest2