Memory alignment
- Apple’s early 8-byte alignment is now 16-byte alignment.
- Isa takes 8 bytes an object pointer takes 8 bytes
- Object minimum 16 bytes. The true object size depends on attributes and memory alignment
- IOS memory is in little-endian alignment mode
Why 16 byte alignment
- Easy to read CPU access data, to do the range of the block to read, if the data read is not aligned, the data read will take more times to complete, which means increased CPU read load.
- Because the nature of an object isa structure, and the first attribute is isa pointer (8 bytes), 8 bytes will be reserved in the absence of other attributes, for the purpose of data read security, if not reserved, may cause data read chaos.
- In the byte alignment algorithm, alignment is mainly
object
And the essence of the object is a struct objc_objectThe structure of the body
.The structure of the body
In memoryContinuous deposit
, so you can use this to perform strong rotation on the structure.
Principles of memory alignment
- 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 from the size of the member or the size of the member’s children (as long as the member has children, such as arrays). Structure, etc.) (for example, if int is 4 bytes, it is stored from the address that is a multiple of 4.
- Struct as members: If a structure has some struct members, the structure members are stored from an integer multiple of the size of the largest element in the structure.
- The total sizeof a structure, the result of sizeof, must be an integer multiple of its largest internal member. What is lacking must be made up.
It’s a little hard to understand, but here’s an example:
Memory Alignment Steps
struct LGStruct1 {
double a; / / 8 (0 to 7)
char b; // 1 [8 length 1] (8)
int c; // 4 [9 length 4] 9 10 11 (12 13 14 15)
short d; // 2 [16 length 2] (16 17)
}struct1;
struct LGStruct2 {
double a; / / 8 (0 to 7)
int b; //4 (8 9 10 11)
char c; / / 1 (12)
short d; //2 13 (14 15) -16
}struct2;
/ / 15 - > 16
Copy the code
Take struct1 as an example:
- 8 is a multiple of 1. Int is a multiple of 4. 9 is not a multiple of 4. Int c falls into position (12, 13, 14, 15) until position 12 meets the rule. Short takes up 2 bytes, at which point the space reaches position 16. 16 is a multiple of 2. At this point, the interior occupies a position (0-17) of size 18.
- Calculate the memory size of the maximum attribute of all attributes
In this case double is the largest, 8.- Calculate the size of the structure in the same way if the property is still a structure
- In this example, 18 is not a multiple of 8. 24 is the smallest multiple of the memory occupied by the largest internal member (double). So struct1 occupies 24 memory. Similarly, struct2 occupies 16 memory. Obviously, the internal type is the same, but the size is different?
The system will do a property rearrangement
Obviously, the internal type is the same, but the size is different? Apple rearranges the memory for the age, C1, and C2 attributes. The age type occupies 4 bytes, while the C1 and C2 char each occupies 1 byte4 + 1 + 1
In the way of, according to8 byte alignment
The way to make up for the shortfallStored in the same block of memory
Middle, let’s do thatOptimization of memory
.
Structure nesting
struct Struct1{
// The position occupied by the start position of bytes
char a; / / 1 0 0
int b; // 4 4 4 5 6 7
short c;// 8,9
}struct1; // Struct1 takes 12 bytes
struct Struct2{
// The position occupied by the start position of bytes
int a; // 4 0 0 1 2 3
double b; / / 8 8 8 to 15
char c; 16 16 / / 1
struct Struct1 struct1;// struct1 char(20),int(24-27),short(28,29),short(28,29) Is a multiple of int.
short d; // 2 32 32 33
}struct2;// Members (including the largest member int (4 bits)) are double (8 bits), so struct2 is an integer multiple of 8 (40 bits)
Copy the code
Sizeof (struct2) is 40.
Analysis of the
- The multiple of int4, the maximum member of a Struct1, is 12.
- Struct2 struct1 the starting position in the largest members of the multiple reference struct1, namely the starting position is the minimum ratio is greater than 16 int: 20, so the struct1 char started from 20; The vacancy up to an int multiple of 24 starts with int B. Short c is 28 and 29. Struct1 Struct1 is 10 from 20 to 29, not the maximum int multiple, so Struct1 Struct1 is empty to 31, Struct1 Struct1 is 12 bytes
- Short D starts at 32 and accounts for 32 and 33.
So Struct2 takes up an integer multiple of the space occupied by the largest internal member, i.e., a double (8 bytes) integer multiple, i.e., 40 bytes.
sizeof
,class_getInstanceSize
andmalloc_size
Take a look at an example:
@interface LGPerson : NSObject
@property (nonatomic, copy) NSString *name;/ / 0 to 7
@property (nonatomic, copy) NSString *nickName;/ / 8 to 15
@property (nonatomic, assign) int age;/ / 16-19
@property (nonatomic, assign) double height;/ / 24 to 31
@property (nonatomic) char c1;/ / 32
@property (nonatomic) char c2;/ / 33
@end
Copy the code
LGPerson *person = [LGPerson alloc];
person.name = @"Cooci";
person.nickName = @"KC";
person.age = 18;
person.c1 = 'a';
person.c2 = 'b';
person.height = 123.5;//double
NSLog(@"%@ - %lu - %lu - %lu",person,sizeof(person),class_getInstanceSize([LGPerson class]),malloc_size(( __bridge const void(*)person))); Print result: <LGPerson:0x100705090> - 8 - 40 - 48
Copy the code
sizeof
sizeof
To calculateMemory size occupied by the type
, which can be putBasic data types, objects, Pointers
-
For basic data such as int, sizeof is the sizeof the memory used by the data type. Different data types have different sizes
-
For instance objects like NSObject, the object type is essentially a pointer to a structure, so sizeof(objc) prints the sizeof a pointer to objc, and we know that a pointer has a memory sizeof 8, So sizeof(objc) prints 8. Note: the 8 bytes here have nothing to do with the ISA pointer!!)
-
For Pointers, sizeof prints 8, because a pointer has a memory sizeof 8,
-
class_getInstanceSize
class_getInstanceSize
Used forGets the amount of memory used by instance objects of the class
And returns the exact number of bytes, essentiallyGets the memory size of a member variable in the instance object
.-
Class_getInstanceSize ([LGPerson class]) is 40
- name String 8 0-7
- nickName string 8 8-15
- age int 4 16-19
- height long 8 24-31
- The maximum attribute string is an integer multiple, so 40
-
The true alignment for an object is 8-byte alignment, which is more than enough for the object. Objc4-818.2 objC4-818.2
size_t class_getInstanceSize(Class cls) { if(! cls)return 0; return cls->alignedInstanceSize(); } uint32_t alignedInstanceSize() const { return word_align(unalignedInstanceSize()); } #ifdef __LP64__ / / 64. # define WORD_MASK 7UL ... #else //WORD_MASK bit byte alignment algorithm static inline size_t word_align(size_t x) { return (x + WORD_MASK) & ~WORD_MASK; // 64-bit 8-byte alignment } Copy the code
-
malloc_size
malloc_size
The function isGets the actual memory size allocated by the system
- In this example, 32 is returned
malloc_size
: in this paper,16-byte alignment
The actual size of memory allocated by the object must be an integer multiple of 16- In malloc source code
#define SHIFT_NANO_QUANTUM 4 #define NANO_REGIME_QUANTA_SIZE (1 << SHIFT_NANO_QUANTUM) / / 16 // 16-byte alignment static MALLOC_INLINE size_t segregated_size_to_fit(nanozone_t *nanozone, size_t size, size_t *pKey) { / /... // (size + 15) >> 4 << 4 multiples of 16 bytes aligned k = (size + NANO_REGIME_QUANTA_SIZE - 1) >> SHIFT_NANO_QUANTUM; // round up and shift for number of quanta slot_bytes = k << SHIFT_NANO_QUANTUM; // multiply by power of two quanta size.return slot_bytes; } Copy the code
other
Apple memory alignment algorithm
At present, there are two known 16-byte memory alignment algorithms, which are mentioned in OC object principle alloc and init source code analysis.
alloc
(objc4-818Source code analysisalign16
:malloc
(Libmalloc – 283.100.6Source code analysissegregated_size_to_fit
align16
static inline size_t align16(size_t x)
{ //16 bytes are aligned to multiples of 16
return (x + size_t(15)) & ~size_t(15);
}
Copy the code
segregated_size_to_fit
#define SHIFT_NANO_QUANTUM 4
#define NANO_REGIME_QUANTA_SIZE (1 << SHIFT_NANO_QUANTUM) / / 16
static MALLOC_INLINE size_t
segregated_size_to_fit(nanozone_t *nanozone, size_t size, size_t *pKey)
{
size_t k, slot_bytes;
if (0 == size) {
size = NANO_REGIME_QUANTA_SIZE; // Historical behavior
}
k = (size + NANO_REGIME_QUANTA_SIZE - 1) >> SHIFT_NANO_QUANTUM; // round up and shift for number of quanta
slot_bytes = k << SHIFT_NANO_QUANTUM; // multiply by power of two quanta size
*pKey = k - 1; // Zero-based!
return slot_bytes;
}
Copy the code
The article lists
- IOS Articles List