Three ways to get memory size

1.1 sizeOf
  • sizeofIs an operator, not a function
  • sizeofWhen you calculate the size of memory, you pass mainly objects or data types inThe compilation phase of a compilerThe size is determined
  • sizeofThe calculated result is occupancySize of space
1.2 class_getInstanceSize
  • class_getInstanceSizeRuntime API for obtainingSize of memory occupied by class instance objectsIs essentially calculating theThe memory size of all member variables in the instance
1.3 malloc_size
  • malloc_sizeGets the actual memory size allocated by the system
1.4 code sample
@interface LGPerson : NSObject @property (nonatomic, copy) NSString *name; @property (nonatomic, assign) int age; @end #import <Foundation/Foundation.h> #import "LGPerson.h" #import <objc/runtime.h> #import <malloc/malloc.h> int main(int argc, const char * argv[]) { LGPerson *p = [LGPerson alloc]; NSLog(@"p object type size: %lu",sizeof(p)); NSLog(@"p object memory size: %lu",class_getInstanceSize([p class])); NSLog(@"p object actual memory allocation: %lu",malloc_size((__bridge const void*)(p))); return 0; }Copy the code

The print result is as follows:

conclusion
  • sizeofThe printedpFor the objectPointer to the addressThe size of a pointer is8byte
  • class_getInstanceSizeIt prints the insideMember variablesThe size of theisaAccount for8bytenamestring8byteage inttype4byte8 + 8 + 4 = 20Because the member variables of a class follow8Byte alignment rule20 - > 24
  • malloc_sizeThe actual size allocated to the system, the size allocated to the object is based on16Byte alignment,16The algorithm of byte alignment is simply understood as24+(16 -1 )>>4 <<4get32

Second, memory alignment rules

  • [Principle 1] The alignment rules of data members can be understood asmin(m, n), where M represents the starting position of the current member,nRepresents the number of bits required by the current member. If the conditions are metmaliquotn(i.e.m % n == 0),nmLocation starts storage, otherwise continue checkingm+1Can be divided exactly byn, until it is divisible, thus determining the starting position of the current member.
  • When a structure has a nested structure, the length of the structure itself as a data member is the memory size of the maximum member of the external structure, such as the structureaNested structuresb.bThere arechar,int,doubleSuch as,bIts own length is8
  • The memory size of the final structure must be an integer multiple of the size of the maximum member memory in the structure.

Verification rules

1.1 Size of bytes for each data type

1.2 Create two different structures myStuct1 and verify myStruct2 respectively with the following code
struct myStruct1 { char a; // 1 double b; //8 int c; //4 short d; //2 }myStruct1; struct myStruct2 { double b; //8 int c; //4 short d; //2 char a; //1 }myStruct2; NSLog(@"%lu-%lu",sizeof(myStruct1),sizeof(myStruct2));Copy the code

The output is as follows: 24-16

Result analysis: The member variables of the two structures are consistent, but the only difference is that the member variables are placed in different order, which results in different memory sizes. This is memory alignment, which is analyzed according to the memory alignment rules:

Analyze the structure myStruct1
  • 【 1 】aAccount for1Byte slave position0start1 = = 0 0% 0The location of the deposita
  • 【 2 】bAccount for8Byte slave position1start1% 8Is not equal to0Move to the8 8 = = 0 8% 8-15b
  • [3]cAccount for4Byte slave position16start16% 4Is equal to the0 16-19c
  • [4]dAccount for2Byte slave position2020% 2Is equal to the0 20-21d
  • [5] Rule three, the memory size must be the largest member in the structure8An integer multiple of,22become8Becomes a multiple of24
Analyze the structure myStruct2
  • 【 1 】bAccount for8Byte slave position0start1 = = 0 0% 7The location of the depositb
  • 【 2 】cAccount for4Byte slave position8start8% 4Is equal to the0 8 to 11c
  • [3]dAccount for2Byte slave position12start12% 4Is equal to the0 12-13d
  • [4]aAccount for1Byte slave position14start14% 1Is equal to the0 14a
  • [5] Rule three, the memory size must be the largest member in the structure8An integer multiple of,14become8An integer multiple of PI becomes PI16
1.3 Add a structure myStruct3 nested with myStrct2 code as follows
struct myStruct2 { double b; //8 int c; //4 short d; //2 char a; //1 }myStruct2; struct myStruct3 { double b; //8 int c; //4 short d; //2 char a; //1 struct myStruct2 str; }myStruct3; NSLog(@"%lu",sizeof(myStruct3));Copy the code

The following output is displayed: 32

Analyze the structure myStruct3
  • 【 1 】bAccount for8Byte slave position0start1 = = 0 0% 7The location of the depositb
  • 【 2 】cAccount for4Byte slave position8start8% 4Is equal to the0 8 to 11c
  • [3]dAccount for2Byte slave position12start12% 4Is equal to the0 12-13d
  • [4]aAccount for1Byte slave position14start14% 1Is equal to the0 14a
  • [5]strIs a struct. Members of a rule two struct are stored from integer multiples of the size of their largest internal member, whilemyStruct2The largest member size is8sostrFrom you to8The current value is15So it doesn’t meet the requirements, so I need to move back to16.16is8An integer multiple of the value of, complies with the memory alignment principle, so16-31savestr
  • [5] Rule three, the memory size must be the largest member in the structure8An integer multiple of,32Just meet

Fourth, memory optimization

Thinking about memory optimization

So, following up on that, why do you want to align memory, when apple is doing this to make the CPU read memory more efficiently, to trade space for time

So we’re going to create a class LGPerson and we’re going to create some properties and assign them to see what the memory placement looks like, okay? Code is as follows:

@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic,assign)int height;
@end
LGPerson *p = [LGPerson alloc];
p.name=@"lb";
p.nickName=@"LB";
p.age=18;
p.height=180;
Copy the code

Breakpoint to view the memory address of the P object

According to the principle of memory alignment, the first isa, the second name, the third age, the following order. By Po 0x000000B400000012 printing, 0x000000B400000012 printing is not LB but 0x0000000100004010 printing is LB Po 0x0000000100004030 printing is LB that age 0x000000B400000012 and you can see that 0x000000B4 is 180 and 0x00000012 is 18 and you can see that the system is optimized and the properties are rearranged

conclusion

So, here’s a summary of apple’s memory alignment philosophy: Most memory is read by fixed memory blocks. Although we use memory alignment in memory, not all memory can be wasted. Apple automatically rearranges attributes to optimize memory

Why is the allocated memory larger than the actual occupied memory

From the exploration above, we know that the memory of objects is calculated based on the memory size of your member variables by 8-byte alignment but the actual memory allocation is not based on 8-byte alignment but on 16-byte alignment and we can explore the objC source code as follows

Size = CLS ->instanceSize(extraBytes); //alignedInstanceSize() + extraBytes; / / memory alignment method inline size_t instanceSize (size_t extraBytes) const {the if (fastpath (cache. HasFastInstanceSize (extraBytes))) { return cache.fastInstanceSize(extraBytes); } size_t size = alignedInstanceSize() + extraBytes; // CF requires all objects be at least 16 bytes. if (size < 16) size = 16; return size; } uint32_t alignedInstanceSize() const { return word_align(unalignedInstanceSize()); } static uint32_t word_align(uint32_t x) {//x+7 & (~7) --> 8 bytes align return (x + WORD_MASK) & ~WORD_MASK; } # define WORD_MASK 7ULCopy the code

As you can see from the source code, the calculated memory size is actually calculated according to 8-byte alignment

  • class_getInstanceSize: is aligned with 8 bytes, referring to the object’s attribute memory size
  • malloc_size: Uses 16-byte alignment to refer to the memory size of the entire object. The actual memory size allocated by the object must be a multiple of 16

Conclusion:

  • Object size is related to the type and number of member variables
  • Object actual memory is aligned to 8 bytes
  • Object allocation memory size is aligned with 16 bytes.
  • 16 byte alignment method, memory usage x x+15 >>4 <<4 to get the memory allocation size

Ps: Logic education is awesome