Question first:

1, int, bool, float, double, string, pointer address, how much memory? 2. What is the memory size of a system without any attributes? 3. How much memory does an object without any attributes actually occupy? 4. Why are member variables 8-byte aligned and objects 16-byte aligned?

Documents:

1, objc source download opensource.apple.com/tarballs/ob… 2, download opensource.apple.com/tarballs/li libmalloc source code…

Byte alignment

Previously:

Many cpus (such as those based on Alpha, IA-64, MIPS, and SuperH systems) refuse to read unaligned data. When a program asks these cpus to read unaligned data, the CPU goes into exception handling and tells the program that it cannot continue. Therefore, if the compiler does not align memory, it will be difficult to develop on many platforms. The CPU does not access data in bytes. The CPU reads memory in chunks, which can be 2, 4, 8, or 16 bytes. Each memory access incurs a fixed overhead, and reducing the number of memory accesses will improve the performance of the program. So the CPU will normally access operations in 2/4/8/16/32 bytes. These access units, or block sizes, are called memory access granularity. In iOS development, the compiler does memory alignment for us. So you don’t have to worry about that. But if the compiler does not provide these features, and the CPU does not support reading unaligned data, the CPU throws a hardware exception to the operating system, resulting in a 4610% difference. If the CPU supports reading unaligned data, you still incur additional overhead compared to aligned data. Sure, the loss is never as big as 4,610%, but it’s not negligible.

Object size memory open:

The main process for creating an objC object is _class_createInstanceFromZone -> instanceSize -> fastInstanceSize -> align16

static ALWAYS_INLINE id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone, int construct_flags = OBJECT_CONSTRUCT_NONE, bool cxxConstruct = true, size_t *outAllocatedSize = nil) { ASSERT(cls->isRealized()); // Read class's info bits all at once for performance bool hasCxxCtor = cxxConstruct && cls->hasCxxCtor(); bool hasCxxDtor = cls->hasCxxDtor(); bool fast = cls->canAllocNonpointer(); size_t size; size = cls->instanceSize(extraBytes); . } size_t instanceSize(size_t extraBytes) const { 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; } size_t fastInstanceSize(size_t extra) const { ASSERT(hasFastInstanceSize(extra)); if (__builtin_constant_p(extra) && extra == 0) { return _flags & FAST_CACHE_ALLOC_MASK16; } else { size_t size = _flags & FAST_CACHE_ALLOC_MASK; // remove the FAST_CACHE_ALLOC_DELTA16 that was added // by setFastInstanceSize return align16(size + extra - FAST_CACHE_ALLOC_DELTA16); } } static inline size_t align16(size_t x) { return (x + size_t(15)) & ~size_t(15); }Copy the code

It can be seen from the source code that the core method of byte alignment is ALIGN16. The alignment algorithm flow is as follows

Validation:

Create an object with no attributes and print a memory size of 16

@interface ASTest : NSObject @end @implementation ASTest @end ASTest *test = [[ASTest alloc]init]; NSLog(@"%zd", malloc_size((__bridge const void *)(test))); The following output is displayedCopy the code

Get memory size:

Class_getInstanceSize () // the actual sizeof the object, 8 bytes aligned 3. Malloc_size () // the actual sizeof the system memory, 16 bytes aligned to sizeof()

ASTest *test = [[ASTest alloc]init]; NSString *string = @""; NSLog(@"%zd", sizeof(int)); // int takes up 4 bytes NSLog(@"%zd", sizeof(BOOL)); // Bool takes up 1 byte NSLog(@"%zd", sizeof(float)); // Float takes up 4 bytes NSLog(@"%zd", sizeof(double)); // Double takes up 8 bytes NSLog(@"%zd", sizeof(string)); NSLog(@"%zd", sizeof(test)); // Pointer type takes up 8 bytesCopy the code

class_getInstanceSize()

Class_getInstanceSize -> alignedInstanceSize -> word_align

size_t class_getInstanceSize(Class cls) { if (! cls) return 0; return cls->alignedInstanceSize(); } uint32_t alignedInstanceSize() const { return word_align(unalignedInstanceSize()); } #ifdef __LP64__ # define WORD_SHIFT 3UL # define WORD_MASK 7UL # define WORD_BITS 64 #else # define WORD_SHIFT 2UL # define WORD_MASK 3UL # define WORD_BITS 32 #endif static inline size_t word_align(size_t x) { return (x + WORD_MASK) & ~WORD_MASK; }Copy the code

As can be seen from the above source code, the actual memory footprint is 8 bytes aligned

@interface ASTest : NSObject @end @implementation ASTest @end ASTest *test = [[ASTest alloc]init]; NSLog(@"%lu", class_getInstanceSize(ASTest.class)); /// The following output is displayedCopy the code

malloc_size()

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;
}
#define NANO_REGIME_QUANTA_SIZE  (1 << SHIFT_NANO_QUANTUM)  // 16
Copy the code

Through the above source can be seen that the memory system open size is 16 byte alignment

Memory alignment

Memory alignment principles:

1. Data member alignment rules:

A member of a struct where the first data is stored at position 0 and the following data is stored sequentially. The starting location of each member must be an integer multiple of the size of the member.

Structure as a member, s2 as a member of structure S, s2 should be stored at an integer multiple of the size of the largest member in S.

2. The size of the entire structure

The total sizeof the structure (sizeof()) must be an integer multiple of the largest internal member of the structure, complementing the shortfall.

The internal alignment process is as follows

struct MyStruct1 { double a; // 8 [0 8] (0-7) char b; // 1 [8 1] (8) int c; // 4 [9 4] 9 not a multiple of 4: actual (12 13 14 15) short d; // 2 [16 2] (16 17) }struct1; Struct MyStruct2 {double a; struct MyStruct2 {double a; //8 [0 8] (0-7) int c; //4 [8 4] (8 9 10 11) char b; //1 [12 1] (12) short d; //2 [13 2] 13 not multiple: (14 15)}struct2; // The size of the structure needs to be an integer multiple of its internal maximum property: a multiple of 8 greater than 15 --> 16Copy the code

The Apple system optimizes MyStruct1 in the same way as MyStruct2, with attribute rearrangement

Question 1:

See 👆sizeof() 2. See 👆malloc_size() 3. See 👆class_getInstanceSize() 4