Autorelease, AutoRelease Pool and how it works
Autorelease and MRC, ARC
- Autorelease: Under MRC, memory management allows three operations, namely
release
.retain
.autorelease
.release
Makes the object’s reference count immediately -1,retain
Make the object’s reference count immediately +1,autorelease
Also makes the object’s reference count -1, but not immediately -1. Callautorelease
Object will be added toautorelease pool
In, at the right timeautorelease pool
Call to objectrelease
That is, the object is released delayed. - Under ARC, Apple forbids manual calls
autorelease
Methods. use@autorelease
After a block creates an auto-release pool, runtime automatically adds to the objects in the blockautorelease
autorelease pool
A thread’s autorelease pool is a stack of pointers. Each pointer is either an object to release, or POOL_BOUNDARY which is an autorelease pool boundary. A pool token is a pointer to the POOL_BOUNDARY for that pool. When the pool is popped, every object hotter than the sentinel is released. The stack is divided into a doubly-linked list of pages. Pages are added and deleted as necessary. Thread-local storage points to the hot page, where newly autoreleased objects are stored.
This is objC-781 source code nsobject. mm definition of automatic release pool. According to the definition, the auto-release pool is actually a stack containing Pointers. There are two types of Pointers in the stack, one is the object pointer to be released, and the other is the sentinel pointer named POOL_BOUNDARY. The free pools are connected in linked lists, and a Page is typically 4096 bytes in size (a Page in virtual memory). The POOL_BOUNDARY sentinel pointer is used to indicate the end of each pool.
When an autoRelease method is called in MRC or an object is written in @AutoReleaseBlock in ARC, the object is registered in the autorelease pool, and the autorelease pool calls the release method to the object when appropriate.
The Application Kit creates an autorelease pool on the main thread at the beginning of every cycle of the event loop, and drains it at the end, thereby releasing any autoreleased objects generated while processing an event. If you use the Application Kit, 例 句 : It takes time to create your own pools objects within the event loop, however, It may be beneficial to create “local” autorelease pools to help to minimize the peak memory footprint.
This is an introduction to The AutoRelease Pool from Apple in Developer Documentation. As you can see in the main thread, the Appkit framework creates an automatic release pool for the application at the start of each Runloop and releases all objects in the pool at the end of each Runloop. It is important to note that Apple makes a point here: if a large number of AutoReleases are created temporarily in an application, it is better for the developer to create a new release pool to minimize memory spikes.
The principle of
First of all, the simplest code
Let’s write the most common one first@autorelease
The code.When we create a macOS project in Xcode, the main function in the template usually contains a similar piece of code. One of the@autorelease pool
This is the API for using automatic release pools in an ARC environment.
OC to C++
Use the clang-rewrite-objc main.m command in the terminal to convert the main.m file to C++ code files. There will be a lot of code to convert, so let’s focus on it.
In the main function of C++ code,@autoreleasepool{}
Has been converted to the above code. We can see the familiarobjc_msgSeng
This is the soul of OC – message sending. At the same time,@autoreleasepool{}
Turned out to be__AtAutoreleasePool
This appears to be the actual structure of the auto-release pool. Let’s find out where the definition is.
By searching for the keyword, we find its definition statement.
As you can see, the __AtAutoreleasePool structure defines a constructor and a destructor, and calls objc_autoreleasePoolPush() and objc_autoreleasePoolPop().
Objc source
In this step, we go toobjc4-781
Code to find the implementation of the above two methods.As you can see, these two methods are actually calledAutoreleasePoolPage
Of the classpush()
andpop()
Method, in other words,The actual structure of the auto release pool in runtime isAutoreleasePoolPage
That’s what it’s going to look like.
The AutoreleasePoolPage class inherits from AutoreleasePoolPageData
From here, you can see that AutoReleasepool is thread specific. At the same time, thread pools are connected by a bidirectional linked list.
Here is a reference to a memory map shared by a student on the Internet
Next, let’s look at the implementation of several key methods.
autorelease
The first isautorelease
Methods. Calling this method adds the object to the automatic release pool.
The first and second lines do some checks on the parameters passed in. As you can see from the second line, if the object passed in is of type TaggedPointer, such as an NSString created from a literal string of less than or equal to 9 characters, something else will happen.
This method is the key to the AutoRelease method. You can see that the first line uses the hotPage() method to get a recently used Page and then goes to process control.
- If you get the hotPage and the Page is not full, add the object to the Page.
- Is called if the Page is full
autoreleaseFullPage
Method creates a new page, adds objects to the newly created page, and passes the newly created pagehotPage()
Gets the page to be connected. - If hotPage is not retrieved, it will be called
autoreleaseNoPage
Method to create and initialize an automatic release pool.
AutoreleasePoolPage::push()
Earlier we mentioned that the object is called first when added to the automatic release poolobjc_autoreleasePoolPush
Method, which only does the callAutoreleasePoolPage::push()
The role of methods.
The if branch of if-else is the process that Debug will execute if an error occurs, and the code in the else branch will be executed normally. The implementation of the autoreleaseFast() method is given in the previous paragraph, where POOL_BOUNDARY is passed in as the sentinel object. This push() function is called when an automatic release pool is created.
_objc_autoreleasePoolPrint()
Use the _objc_autoreleasePoolPrint (); Extern void _objc_autoreleasePoolPrint(void); extern void _objc_autoreleasePoolPrint(void) . This method will be called AutoreleasePoolPage: : printAll (); Prints information about the auto release pool.
From the printed information, the auto-release pool does correspond to one thread to another, and a sentinel object is added to the pool when it is created, which is consistent with our code analysis above.
Write in the last
That’s about all the principles and code for AutoRelease and autoreleasePool, but there are many more implementations that are not covered in this article. Interested readers can also find the nsobjject. Mm file in the objC4-781 source code for a more detailed study. In general, auto-release pooling delays the life cycle of objects and can automatically release objects that need to be released for developers, reducing the possibility of memory leaks.
Tino Wu.
more at tinowu.top