preface

In most of your work, you will be exposed to the concept of memory alignment, and what is memory alignment? Today I’m going to explore this mystery. Without further ado, let’s look at how objects are stored in memory.

First, we’ll go ahead and create a DMPerson class, instantiate an object and assign values to each of its properties

@interface DMPerson : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) float height;
@property (nonatomic, assign) char flag;

@end

DMPerson *p1 = [[DMPerson alloc] init
p1.name = @"mantou";
p1.nickName = @"MT";
p1.age = 16;
p1.height = 195.3;
p1.flag = 'a';
Copy the code

Then let’s look at its storage in memory

The first column is the address of the object in memory, followed by the corresponding value. Using the same code above, let’s add a little bit of print to see how much memory the object we created is in, how much memory the object type has, how much memory the object at least needs, and how much memory the system actually allocated

NSLog(@"Object type memory size --%lu".sizeof(p1));
NSLog(@"Minimum memory size required for an object --% LU".class_getInstanceSize([p1 class]));
NSLog(@"System allocated memory size --% LU".malloc_size((__bridge const void *)(p1)));
Copy the code

The results are as follows

The result was something of a surprise to me: the amount of memory the object required was not the same as the amount of memory the system actually allocated. Let’s start with the conclusion:

  • In THE C language,sizeof()Is an operator that determines the data type or the length of an expression.sizeof()Evaluation of occurs at compile time, so it can be used as a constant expression. whilesizeof(p1)Print isp1The type of is the object, which is essentiallyStructure pointer
  • class_getInstanceSizeThe printed result is the minimum memory size required for the object, which we created hereDMPersonThe class has a total of five properties, including twoNSString1,int1,float1,charType. Plus the class itselfisaI need 8 bytes, soDMPersonClass needs at least 8+8+8+4+4+1 = 33 and then8-byte alignment, so the printout is 40.
  • malloc_sizeThe printed result is the actual memory allocated by the system, which we calculated earlierDMPersonA class needs at least 40 bytes to be stored completely, and the actual allocation of a class in memory is16-byte alignmentSo the final result is 48.

Memory alignment

In the previous exploration, we learned that different data types occupy different sizes in memory. Let’s first steal an image and see how many bytes each type occupies (pretend @cooci).

Let’s say we have an object that has a property of type double, a property of type bool, and an property of type int. According to the comparison in the table, we need a total of 8+4+1=13 bytes to store it. If we arrange it in order, it will look like the following

Each time we read the data, we need to change the size of the data we read. For example, we read 8 bytes firstdouble“, and then in the read 8 bytes, found unsuccessful, read another 1 bytes, readboolAnd then read 1 byte later, and found that it was not successful, and finally changed to read 4 bytes, which is very low efficiency, so the system did some optimization when storing data, which is what we calledMemory alignment. It should actually be stored as shown in the following figure

Here’s another example:

struct LGStruct1 {
    double a;      
    char b;         
    int c;          
    short d;        
}struct1;

struct LGStruct2 {
    double a;       
    int b;          
    char c;       
    short d;  
}struct2;

NSLog(@"%lu-%lu".sizeof(struct1),sizeof(struct2));
Copy the code

If these two constructions contain exactly the same elements, will they sizeof print the same? Let’s see what happens:

2021- 06- 09 00:20:14.623807+0800 001- Memory alignment principle [9031:384474] 24- 16
Copy the code

It turns out that two constructs that contain exactly the same contents are not the same because of the order of the variables. So why? Because of memory alignment, certain principles need to be followed.

Principles of memory alignment

  1. Data member alignment principle: (struct) Or in combination with (union), the first data member is placed inoffsetfor0In the future, the starting position for each data member storage starts with an integer multiple of the size of that member or the size of its children (as long as that member has children, such as arrays, structures, etc.)intfor4Byte, from4Integer multiples of address start storage)
  2. Structure as a memberIf a struct has some struct members, the struct members are stored starting at an address that is an integer multiple of the largest internal element size. (struct aThe entitiesstruct b.bAre there inchar.int.doubleAnd so on, sobShould be from8Is an integer multiple of.
  3. Finishing touches: the size of the structure, i.esizeofThe result of must be an integer multiple of its largest internal member, and any shortfall must be made up

Structure alignment (no nesting)

For example, how do these two structures store data in accordance with the memory alignment principle, as shown in the following figure

The final number of bytes is18According to the last item of memory alignment principle, it needs to be completed as its internal maximum memberdouble aWhat occupy a space8Integer multiples of bytes, so phi is equal to phi24Bytes.The final number of bytes is16According to the last rule of memory alignment,16Byte is its largest internal memberdouble aWhat occupy a space8Integer multiples of bytes, so phi is equal to phi16Bytes.

Finally, we come to the same conclusion as the printed result above, indicating that the system does follow this principle for data storage

Structure alignment (structure nesting)

Let’s look at another example of struct nesting

struct LGStruct1 {
    double a;      
    char b;         
    int c;          
    short d;        
}struct1;

struct LGStruct3 {
    double a;
    int b;   
    char c;   
    short d;  
    int e;   
    struct LGStruct1 str; 
}struct3;

NSLog(@"%lu".sizeof(struct3));
Copy the code

Again, let’s look at the system first

2021- 06- 09 00:44:54.039441+0800 001- Memory alignment principle [9380:400671] 48
Copy the code

And his specific storage ideas, as shown in the figure

Due to thestruct LGStruct1 strIs also a structure, so it needs to be byte aligned internally, and finallystrThe number of bytes is24Bytes. In accordance with theMemory alignment principleArticle 2,strNeed from24Location to start storage occupancy24Bytes. The number of bytes occupied is48Bytes.

Here are two more examples

struct DMStruct1 {
    double a;
    char b;
    int c;
    short d;
}struct1;

struct DMStruct2 {
    short a;
    char b;
}struct2;

struct DMStruct3 {
    double a;
    int b;
    char c;
    short d;
    int e;
    struct DMStruct2 sss;
    struct DMStruct1 str;
}struct3;

struct DMPerson4 {
    double a;
    int b;
    char c;
    short d;
    int e;
    struct DMStruct1 str;
    struct DMStruct2 sss;
}struct4;


NSLog(@"%lu-%lu".sizeof(struct3),sizeof(struct4));
Copy the code

Their final memory distribution is shown in the following figure

The laststruct3As a result of the48Byte, andstruct4As a result of the56Bytes.

2021- 06- 09 02:24:50.797370+0800 001- Memory alignment principle [11167:486569] 48- 56
Copy the code

As you can see, structures within structures are also stored as a whole and need to be in-memory aligned.

At this point, we can conclude that for structures, the system does store data according to memory alignment principle. So we know that in iOS, objects are actually structures, so can we test that with the theory of structure alignment? Let’s move on

Memory optimization

Let’s modify the above code to change the location of the properties in DMPerson

@interface DMPerson : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) char flag;
@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, assign) float height;

@end
Copy the code

Then continue printing as assigned above

The discovery is exactly the same as the previous output. And then we print each of them one by oneWe find that the system is actually right at the object levelMemory alignmentIt’s optimized, no matter how your properties are arranged, the system will store the data in memory in the best order.

conclusion

The data storage of the system is aligned according to the principle of memory alignment. For structures, the order of members may cause a certain amount of memory space waste. For objects, the iOS system has helped us optimize the memory to ensure the optimal storage mode. Therefore, in the future development process, if the structure type is used, special attention should be paid to memory alignment issues.