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 mainlyobjectAnd the essence of the object is a struct objc_objectThe structure of the body.The structure of the bodyIn 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:

  1. 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.
  2. 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
  3. 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 + 1In the way of, according to8 byte alignmentThe way to make up for the shortfallStored in the same block of memoryMiddle, 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

  1. The multiple of int4, the maximum member of a Struct1, is 12.
  2. 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
  3. 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_getInstanceSizeandmalloc_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

  • sizeofTo 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_getInstanceSizeUsed forGets the amount of memory used by instance objects of the classAnd 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_sizeThe function isGets the actual memory size allocated by the system
    • In this example, 32 is returned
    • malloc_size: in this paper,16-byte alignmentThe 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