preface
Autorelease Apple documentation
-
Autorelease Pools provides a mechanism to delay sending release messages to objects. It avoids when you want to relinquish ownership of an object but don’t want to release it right away (such as when you return an object from a method).
-
For example, when we create an object and put it into the automatic release pool, it will not be released immediately, but will wait until a runloop ends or the scope is out of {}.
Relationship between Autoreleasepool and Runloop
- The main thread of the
NSRunLoop
Each time the event response is detected to openevent loop
Previously, one was created automaticallyautorelease pool
And will be inevent loop
Execute at the enddrain
Action to release the object - If our program creates a large number of temporary variables, we can
Autoreleasepool
To reduce memory spikes.
Relationship between Autoreleasepool and threads
- Each thread, including the main thread, maintains its own auto-free pool stack structure
- [Fixed] New auto-release pools are added to the top of the stack when created. It is removed from the stack when the autofree pool is destroyed
- For the current thread, the auto-free object is placed at the top of the auto-free pool stack; When a thread stops, all automatic release pools associated with that thread are automatically released
Clang analysis
Create a new project as follows:
Enter themain.m
For the directory where the file resides, enterclang -rewrite-objc main.m -o main.cpp
Will generate ac++
file
@autoreleasepool
The bottom layer is a structure- in
{}
Is called in scopeobjc_autoreleasePoolPush()
Constructor sumobjc_autoreleasePoolPop()
The destructor
Continue adding a symbolic breakpoint for objc_autoreleasePoolPush: find the source code implementation in objC
Autoreleasepool structure analysis
Open objC source code, search for objc_autoreleasePoolPush,
Found that calledAutoreleasePoolPage
The inside of the classpush
Method, when we analyze the source code do not rush to see, we should first to understand the underlying structure.
Structure analysis
AutoreleasePoolPage inherits from AutoreleasePoolPageData
magic
: Used to detectAutoreleasePoolPage
Is the structure complete, occupying 16 bitsnext
: indicates the latest additionautoreleased
Object at the next location to which it points when initializedbegin()
, occupying 8 bitsthread
: refers to the current thread // occupies 8 bitsparent
: refers to the parent node, the first nodeparent
A value ofnil
Take up eightchild
: refers to the child node, the last nodechild
A value ofnil
Take up eightdepth
: represents depth, from0
Start and increase1
Take up to fourhiwat
: The maximum number of pushmarks occupies 4 bits
Understand the structure through comments
- one-thread
autorealse pool
It’s a bunch of Pointers - There are two types of pointer: the object to be released and the POOL_BOUNDARY. The boundary tells us whether the page object has been deleted.
- The collection structure of this pointer is actually one
Double linked list structure
. Pages are related to each other. - The current thread stores locally the hot page object that points to the newly automatically released hot page
Adding an Object process
autoreleaseFast
Called in non-bug modeautoreleaseFast
autoreleaseFast
call
- if
page
Stored in and not full, directly inpage
After adding - if
page
Full of callautoreleaseFullPage
- If there is no
page
callautoreleaseNoPage
AutoreleaseNoPage process
- Create a new page and set it to HotPage
- for
page
addPOOL_BOUNDARY
The border page
Add an obj object, a page can be viewed as a single linked list,page->add
This is equivalent to adding an obj object to the end of the list.
AutoreleaseFullPage process
- So this is essentially finding the end of the double-linked list
page
, exit the loop,page
Add the correspondingobj
The size of the page
There is a macro definition in the source code
-
So a page size is 1<<12, which is 4096.
-
But how many objects can a page store? , page itself attribute size = magic+next+ Thread +parent+ Child +depth+hiwat = 56, if the home page also has a boundary object POOL_BOUNDARY occupies 8 bytes.
-
So first page, objcCount = (4096-56-8) /8 = 504,
-
If it’s not the home page with no boundaries, it’s 505 objects
Verify page size
_objc_autoreleasePoolPrint
You can print the page information with 506 local variables generated as follows
- There are two pages, the first page is full with 504 objects, and the second page has two
AutoreleasePool nested
Curious what the structure of the page looks like if AutoreleasePool is nested, do the following test
View the print result:
- When the first automatic release pool
page
When the pool is not full, objects from the nested auto-release pool continue to be added later. - Whenever you create an auto-release pool, a boundary object is created.
Automatic release pool release
call_objc_autoreleasePoolPop
methods pop
The key method is calledpopPage
The rest of the code is debug related and does not affect the main flowEnter the popPage
releaseUntil
The key method is to call the Page ->releaseUntil method and repeatedly call objC_Release (obj) to send a release message to obJ.
- It’s pretty easy to implement with one
while
Cyclic continuous releaseAutoreleasePoolPage
Untilnext
Points to thestop
- use
memset
Set the contents of memory toSCRIBBLE
And then useobjc_release
Release the object.
conclusion
Here’s another diagram to summarize the auto-release pool, because graphics are more memorable.