preface
IOS underlying principle 1 — alloc exploration we have a preliminary study of the alloc underlying, so here we go a little further, continue to use obj4818.2 source code
alloc
Process in-depth analysis
- Create a class and set a breakpoint
- Open assembly call:
Debug
->Debug Workflow
->Always Show disassembly
So if we run this code we’ll see that after XKPerson is objc_alloc, what is that? So let’s make a symbolic break point and find out. Here is a screenshot of how to make a symbolic breakpoint:
After setting a sign breakpoint, we also set a breakpoint for the alloc method
Shut down Always Show DisAssembly at this point, and let’s start running the code and see what happens.
We’ll see that the code actually goes to the objc_alloc symbol breakpoint, and we’ll continue running, and then the code comes to the alloc breakpoint. How can objc_alloc be called when it should be called directly? Why is that? This is actually because LVVM is optimized and it does something. To be continued…
Memory alignment
Today we’re going to focus on memory alignment. Normally when you create a class you have a lot of attributes, class methods, instance methods, member variables so how are these stored in memory space? How much memory does it take up? What are the principles followed? Let’s find out.
Firstly, the factors affecting the memory size of class objects are explored
- Create a class and see how much memory its class objects occupy.
Result: The memory size is 8 because there is at least oneisa
The existence of, whileisa
Is exactly 8 bytes in size
Note: class_getInstanceSize is used to get the memory size of the instance object of the class and returns the number of bytes, essentially getting the memory size of the member variables in the instance object
- Add a property to the class
Result: The memory size is 16, and the size of the name attribute is 8 bytes
- Add a member variable to the subclass
Result: The memory size is 24, and the size of the visible member variable is 8 bytes
- Add a class method and an instance method to the subclass
Result: Memory size 24, visible method size is 0 bytes
The following conclusions can be drawn from the above four steps:attribute
andMember variables
Can affect object memory size,methods
Object memory size is not affected. Since the nature of the attribute is:Member variables
+The get method
+Set method
, so the final conclusion:Member variables are fundamental factors affecting the size of an object's memory.
Second, the amount of memory occupied by various data types
In the above exploration, we can see that different data types take up different amounts of memory space. The following figure shows the size of bytes for each type
Finally, the three basic principles of memory alignment
- 1. Data member alignment rules
The data member of a struct(or union), the first data member is placed at offset 0, and the starting position of each data member is an integer multiple of the size of the member or its children (as long as the member has children, such as arrays, structures, etc.) (e.g., int is 4 bytes, Start with an integer multiple of 4.
- 2. Structure as a member
If a structure has some structure members, then the structure members are stored from an integer multiple of the size of the largest element in the structure (struct A contains struct B, char, int, double, etc.), since double takes up 8 bytes
- 3. Total size of the structure
The total sizeof the structure, the result of sizeof, must be an integer multiple of the largest member within the structure
Memory Alignment cases
struct Struct1 { double a; [0 7] char b; [8] int c; [12, 13, 14, 15] short d; [12, 13, 14, 15]; [16 17]}struct1; Struct Struct2 {double a; struct Struct2 {double a; [0 7] int b; [8 9 10 11] char c; // the index 12 is an integer multiple of 1, stored in [12] short d; [14 15]}struct2; // struct struct {double a; // struct struct {double a; [0 7] int b; [8 9 10 11] char c; // the index 12 is an integer multiple of 1, stored in [12] short d; [14 15] int e; [14 15] int e; [16 17 18 19] struct Struct1 STR; [24.....46]}struct3; [24.....46]}struct3; // So the total space of this structure is [0...46], the size is 47 bytes, take the largest element double8 bytes, NSLog(@"\n first struct size :%lu\n second struct size :%lu\n third struct size :%lu", sizeof(struct1), sizeof(struct2), sizeof(struct3));Copy the code
Run result: first structure size :24 Second structure size :16 third structure size :48Copy the code
Memory optimization
#import <UIKit/UIKit.h> #import "AppDelegate.h" #import "XKPerson.h" #import <objc/runtime.h> #import <malloc/malloc.h> int main(int argc, char * argv[]) { NSString * appDelegateClassName; @autoreleasepool { XKPerson *person = [XKPerson alloc]; Person. Name = @" person "; NickName = @" nickName "; person.gender = YES; person.age = 30; NSLog (@ "person - > % @", the person); NSLog (@ "sizeof - > % lu", sizeof (person)); NSLog (@ "class_getInstanceSize - > % zu," class_getInstanceSize ([XKPerson class])); NSLog(@"malloc_size -- >%zu", malloc_size((__bridge const void *)(person))); appDelegateClassName = NSStringFromClass([AppDelegate class]); } return UIApplicationMain(argc, argv, nil, appDelegateClassName); }Copy the code
2021-06-09 17:39:56.653496+0800 memoryDemo[12103:551583] person -- ><XKPerson: 0x600003AA6970 > 2021-06-09 17:39:56.653978+0800 memoryDemo[12103:551583] sizeof -- >8 2021-06-09 17:39:56.654064+0800 MemoryDemo [12103:551583] class_getInstanceSize -- >40 2021-06-09 17:39:56.654195+0800 memoryDemo[12103:551583] Malloc_size -- >48 (LLDB) x/6gx person 0x60000287EFD0:0x0000000100a9a770 0x000000000000001e 0x60000287efe0: malloc_size (LLDB) x/6gx person 0x60000287EFD0:0x0000000100a9A770 0x000000000000001e 0x60000287efe0: 0x0000000100a95020 0x0000000100a95040 0x60000287eff0: 0x00000000000000BE 0x0000000000000000 (LLDB) Po 0x0000000100A95020 Bit gold (LLDB) Po 0x0000000100A95040 a word is dry (LLDB) Po 0x00000000000000be 190 (lldb) po 0x000000000000001e 30Copy the code
Description:
-
Sizeof measures the memory sizeof data (dictionaries, arrays, variables, structures, etc.). Person is an object whose structure pointer is essentially 8 bytes
-
Class_getInstanceSize calculates the memory used by the object and its member variables, paying attention to the parent class attributes and ISA, 8-byte alignment
-
Name(NSString8 bytes)+nickName(NSString8 bytes)+age(int4 bytes)+height(long8 bytes)+ ISA (object pointer 8 bytes) = 36 bytes. The value is 40 bytes according to the 8-byte alignment rule
-
Malloc_size should apply for 40 bytes of memory. However, following the 16-byte alignment principle, malloc_size applies for a multiple of 16 bytes of memory, and finally applies for 48 bytes of memory.
Green hills never change, green waters always flow. More exciting underlying principles will continue, stay tuned…