iOS uses Instruments to optimize memory performance

iOS uses Instruments to optimize memory performance

question

The project uses pictures to synthesize video, and it is found that the memory grows very rapidly, which leads to some problems caused by memory. This article uses this case, combined with the Instruments tool to detect and analyze the problem, and finally solve the memory problem.

Demo code ScreenRecorderTest2 of this article

Instruments detection

View memory growth within a range

  1. Open Instruments, select the Allocations tool, and click the Record button to record
  2. Use the mouse box to select the area where the memory grows, the highlighted area in the two black lines in the figure

View memory growth within a range

  • The chart area above is a visual view of memory
  • The panel area below shows specific statistics.
    You can see that the overall memory growth is 16.81M (All Heap Allocations heap memory allocation)

Detailed statistics of heap memory allocation
Click the small arrow button next to All Heap Allocations to see detailed statistics of heap memory allocation: Detailed statistics on heap memory allocations

  • Address: The memory address of the data
  • Timestamp: The time the data was created
  • Size: the size of the data
  • Responsible Library: related libraries for data creation
  • Responsible Caller: function call of the library related to data creation

In the statistics table, it can be seen that the AppleJPEG library calls the applejpeg_decode_create method to create a lot of memory data. The

 right area displays the function's call stack information panel (Stack Trace), and the I-shaped button in the upper right corner can switch to display system function
callsToggle display of system function calls

Visual display of memory allocation size and corresponding code call information
Click the highlighted code in the call stack to view code details and memory information:
Visual display of memory allocation size and corresponding code call information

The marked area on the right shows the proportion of memory occupied.

analyze

In the above figure, it can be seen that the buffer object and image occupy the largest memory, but the buffer will call CVPixelBufferRelease to release the corresponding memory after each use. There will be no memory problem. If the image object is not released in time, it will be in the entire while loop block. Reserved for a period of time, causing the memory to grow.
In addition, if the image object is not released in time, it is also related to calling CVPixelBufferRelease(buffer) at the same time; if the buffer is not created and released, the growth of the image object will not be obvious, and the release speed is also very fast. The following Two control groups can be compared

Control group 1: only create image objects in the loop memory growth:
memory growth is 2.73M
Control 1: Memory grows only when image objects are created in a loop:

Control group 2: Add autoreleasepool in the loop to create image object memory growth:
memory growth is 492K
Control group 2: Add autoreleasepool to the loop to create image object memory growth

It can be seen from the above that the use of autoreleasepool can effectively solve the problem of memory increase caused by creating a large number of memory-sensitive objects in a loop

Final solution
Using the autoreleasepool block inside the while loop, the arc object is released in time each time the loop, and the memory growth has dropped from the original 16.81M to only 475K
final solution

Code:

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--;
        }
    }
}

Summarize

The above is a summary of using Instruments to solve memory problems. If there is anything wrong, please let me know
. The demo code ScreenRecorderTest2 of this article

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324432441&siteId=291194637