What does Allocations do generally
Allocations are very useful for APP optimization, and are often used to analyze memory leaks, memory increases, and memory usage by parts of your APP. When we know which memory is consuming more, we optimize directly to reduce memory usage, focusing on how can we reduce VM usage, and then analyze Heap usage
The meaning of parameters in Allocations
-
All Heap & Anonymous VM Heap memory + virtual memory
-
All Heap Allocations Heap memory
-
All Anonymous VM virtual memory
-
Persistent represents the number of objects that are using memory
-
# Transient indicates the number of existing objects that have been destroyed. The memory occupied by the object is released
Allocations checks problems that memory is not freed on time
During the ARC process, the memory of objects is not released in time due to circular references or other misuse. This memory will be released when the page is closed, which will cause problems in the detection of “memory leaks”.
Leaks is impossible to detect because the memory is actually being released late rather than not at all.
Using the Mark Generation function at Instruments Allocations helps us troubleshoot this problem.
A typical case
Suppose we have a page MainViewController. After opening this page, the video broadcast will start. During the live broadcast, the memory will not be released in time, for example, the memory usage of the application has reached 200MB after 10 minutes.
In view of such a problem we should how to investigate?
Troubleshooting steps
1. Start Profile in Xcode
2. Select the Allocations tool, and click the red button to start “Record,” at which time Instruments started our application
3. Open a page that has memory free problems and wait for the normal initialization of the page to complete, say 10 seconds
4. Switch to the Display Settings Tab from the area in the lower right corner of Instruments and click Mark Generation to generate the first Generation: Generation A; This is the starting point at which we decide memory was not freed in time
5. In order to accumulate more memory leaks that are not released in time, you can wait a little longer for the second Mark (depending on how long it takes for your memory problem to occur, say 2 minutes), and then click “Mark Generation” again. The memory growth between the two generations is exactly what we are looking for:
6. Click the small arrow for more detailed information, find the highest memory usage based on the percentage, and keep expanding until we find our own code, which is where the problem lies.
Analyzing memory
All Heap Allocations (real memory) was only 23.02, while All Anonymous VM (virtual memory: The amount of virtual memory allocated to an application, which provides enough memory for the application when it needs it rather than creating it on the spot, is as high as 91.06, so the amount allocated to us by the phone is 114.08; Now we do not detect memory leak (it is another tool), so we try to optimize VM (because it is not the actual memory occupied by app, only allocated by the system), and VM is mainly composed of the following three parts (I will run the screenshot after optimizing all three parts).
VM:ImageIO_PNG_Data
I found an explanation for this in Google, which said
Replace:
background.image = [UIImage imageNamed:@"*.png"];
With:
background.image = [UIImage imageWithContentsOfFile:[[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/*.png"]];
and now the ImageIO_PNG_Data's will be released when the view controller is dismissed.
Copy the code
I searched for imageNamed later in my project, and there are a lot of places to use it, so the right way to load an image is like this
1: Large pictures that occasionally need to be displayed should be placed in the project directory, not in assets. xcassets, and loaded with imageWithContentsOfFile so that the system does not cache; 2: For small pictures that often need to be displayed, put them into assets. xcassets for the system to cache, and load them with imageNamed;Copy the code
So I changed a few things, like
imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:nameArr[index] ofType:@"png"]];
//imageView.image = [UIImage imageNamed:nameArr[index]];
Copy the code
The difference between the two:
- ImageNamed by default caches the image in memory after loading the image successfully. This method looks for an image object in the system cache with a given name and returns it. If no image object is found in the cache, it loads the image from the specified location and then caches the object and returns the image object.
- Image with Content file only loads images, not caches.
2. Application scenarios
-
For larger images, which only load once and don’t need much caching, choose Image with Content file
- When the application needs to load a large image and use it once, there is no need to cache the image. Using image with Content file is the most economical way
-
With little performance impact, select imageName:
- Because heavy use of imageNamed increases CPU time to do this, we need to choose carefully depending on the particular scenario
- UIimage is small, but it has a lot of elements and the problem becomes obvious.
VM:CG raster data
I found the explanation about this problem in Google, it is the problem of SDWebImage
* Decompressing images that are downloaded and cached can improve peformance but can consume lot of memory.
* Defaults to YES. Set this to NO if you are experiencing a crash due to excessive memory consumption.
Copy the code
So we need to set it up in the Appdelegate
[[SDImageCache sharedImageCache] setShouldDecompressImages:NO];
[[SDWebImageDownloader sharedDownloader] setShouldDecompressImages:NO];
[[SDImageCache sharedImageCache] setShouldCacheImagesInMemory:NO];
Copy the code
VM:CoreAnimation
There’s no obvious answer to this question when you Google it, so let’s take a look at the detailed list
We can see that there are a lot of places that have this VM problem, so let’s take a look at what the functions are
We can find some systematic methods, we seem to have no way to start; At this point, we can Google it and see that there are many reasons for this, one of which ishere
Found out that animation caused by the inner pages.
Inside the pageViewController(viewController that added to the scrollView as a page) on viewWillDisappear:(BOOL)animated method I added this
for (CALayer* layer in [self.view.layer sublayers]) {
[layer removeAllAnimations];
}
it resolved the problem.
Copy the code
Found out that animation caused by the inner pages we still need to check whether we can locate a page in the extension information (I don’t know how to locate it, please reply to me if you know), So I implemented the above method in all the interfaces I just entered
Look at the optimization results
At this point we reset Allocations, and then repeated the above random clicks, jumps, and so on in our app, and took the screenshot below
One good thing we found was that VM:CG Raster data decreased significantly; At the same time we have a bad phenomenon, the other two terms have not changed significantly, so let’s continue to analyze why, but don’t worry, let’s take a look at the bottom right, what are the functions
Record Settings
Launch Configuration for All Allocations
All Allocations initiate the following configuration: Discard unrecorded data upon stop: Discard events for Freed memory when the user clicked Stop: Events are discarded when memory was freed (that is, events associated with freed memory are not shown in the list) Only Track VM Allocations: Only track VM allocations captures items of virtual memory, without checking, because we still need to look at real memory allocations here we need to tick the first and second
Launch Configuration for Heap Allocations
Start the following configuration for all real memory Allocations (this column cannot operate if you checked Only Track VM Allocations) : Record Reference Counts: Identity virtual C++ objects: enables NSZombie detection, which detects whether a message has been sent to the released object
Recorded Types
I don’t need to explain this, but what type of events do you need to catch on the hook, providing a simple re
Dispalay Settings
Track Display
Decide what to display above
Current Bytes: indicates the number of Bytes. Allocation Density: indicates the number of Bytes. Active Allocation Distribution: indicates the number of newly activated allocations
Generation Analysis
This feature is very useful. It is usually used like this: Mark a page before entering the page, and mark a page when exiting the page to compare what content has been added, to analyze which memory has not been freed. For example, I clicked Mark when we were about to go to the calendar screen
Shows Growth of 27.48, which is the sum of real and virtual memory for the first time; After we’ve been in the calendar screen for a while, let’s click on Mark screenshot
So we know that we have still increased memory by 2.85 when we exit the calendar screen. You can click to see which memory has been increased
Allocation Lifespan
What Allocations All Allocations need to be recorded: All Created & Persistent: Created & alive: Created & Destroyed: Alive we only care about the alive so we check the second one
Allocation Type
Record Allocation types All Heap & Anonymous VM: All real memory and virtual memory, I usually choose this to analyze All Heap Allocations: All real memory All VM Regions: All allocated virtual memory the selection here will affect the list, for example I select All VM Regions
Call Tree
The functionality here requires us to switch the list display type to Call Trees so that we can see the Call tree very clearly
But normally we need to check something, because by default there’s nothing to Separate by Category
VM Separate by Thread: I personally don’t like it very much because I don’t care much about threads
Invert Call Tree Invert Call Tree Invert Call Tree Invert Call Tree Invert Call Tree
Hide System Libraries: This seems to be a must because we currently only care about our own methods and don’t care about System Flatten Recursion. Flat recursion, I don’t know what it is yet, I didn’t find it online, but I hooked it, it sounds like a nice feature
Call Tree Constraints
I don’t need to talk about that, it’s filtering the data in the list, it could be quantity or size; Let’s say I only care about the data up to 100
Data Mining
Data mining, which is a gimmicky feature; The official website offers an explanation
**
Allows you to filter through the collected data for specific symbols and libraries.
Copy the code
Click on the Symbol call and the Library will automatically add the Symbol and Library of the selected line to the small box
Symbols and libraries have two options, that is, whether to filter line changes; Clicking Restore removes the selected row from the small box, as we did with the Help Admin assistant
I don’t think I need data mining for now, so I’ll fill this in later when I’m more familiar with it
Extended Detail
And I actually talked about this already, but for Allocations is the call stack or something that looks at a certain line of data so far there’s only one list presentation we didn’t talk about, so let’s take a look
There are more calls to libraries and methods than Statistics
Continue to optimize
Having said that, we are only happy with the optimization of VM:CG Raster Data. Let’s continue to optimize VM:CoreAnimation and VM:ImageIO_PNG_Data
VM: ImageIO_PNG_Data optimization
Earlier, we changed the method of loading large images to image with Content file, but the effect was not obvious. Now let’s see which method generates a lot of virtual memory. Here are the steps
Check the list
Find the calling function.png
A solution borrowed from Google
//_pageScrollView is a scroll view used to load local images... For (int index = 0; index < nameArr.count; index ++) { UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(index * pageScrollImagewidth, 0, pageScrollImagewidth, pageScrollImageheight)]; NSString *imageFile = [NSString stringWithFormat:@"%@/%@.png",[[NSBundle mainBundle] resourcePath],nameArr[index]]; @autoreleasepool { imageView.image = [UIImage imageWithContentsOfFile:imageFile]; } // imageView.image = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:nameArr[index] ofType:@"png"]]; // imageView.image = [UIImage imageNamed:nameArr[index]]; [_pageScrollView addSubview:imageView]; }... - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; for (UIView *viewView in _pageScrollView.subviews) { [viewView removeFromSuperview]; } _pageScrollView = nil; }Copy the code
Following this method, the effect is still very clear, before it was 33.95 (see the image above).
Optimization of VM: CoreAnimation
We have also tested this problem using Generations
As mentioned above, we can use the following methods to reduce Google
for (CALayer *layer in self.view.layer.sublayers) {
[layer removeAllAnimations];
}
Copy the code
Render::Shmem::new_shmem(unsigned long); Render::Shmem::new_shmem(unsigned long); There are two descriptions in this article
The solution is to reduce that space to an absolute minimum. I am having the same issue. I will try what you suggested with the size. But, Maybe changing the background color from clearColor could correct the issue as wellCopy the code
I tried changing the background color. Nothing
[[UIView appearance] setBackgroundColor:[UIColor whiteColor]];
[[UIView appearance] setBackgroundColor:[UIColor clearColor]];
Copy the code
Therefore, we will not solve this problem for the time being. I will supplement it here when I solve it later. VM:Animation optimization is a big problem and may need a separate article
Look at the other part
If you want to use this view, you need to manually capture (or you need to hook Automatic Snapshotting) the list in the lower left corner
There are three types of data displayed by default: Dirty data Size (which cannot be reused) Swapped Size: Resident Size: fixed data Size You can see here for an explanation of these three names, so we know that this data is abnormal
Because 31.54 garbage data was generated, we found the answer we were looking for here, which turned out to be invalid and from here we know that we don’t need to deal with this problem, because the XCode tool itself is not our program so we move on to the next question
I did a special reboot to prove that I wasn’t doing anything else, and the result was still a lot of garbage data
Why is that? The answer is here, so we do not need to deal with this part, so our program did not have a lot of garbage data, the problem is still CoreAnimation
We’ll leave this problem as it’s the same problem as optimizing VM:CoreAnimation above, and I’ll add it when I’m more familiar with it
Regoins Map
This view, which basically shows you the address segment and call path of each piece of data, I rarely use this view, but it’s nice to see path
What does Allocations do generally
The text has already covered this, but Allocations is very useful for APP optimization, often analyzing memory increases (not necessarily memory leaks) and memory Allocations among parts of APP, and when we know which memory is more expensive, This article has been discussing how to reduce VM usage. You can then analyze Heap usage
reference
Use Instruments Allocations to troubleshoot late memory Allocations
Instruments learning Allocations # memory management in iOS