iOS大師班01 - alloc淺析

知道中國最著名的女程序員是誰麼?----- 宋丹丹!程序員

至於爲啥看看下面這組圖你就知道了算法

放錯了,是下面這組app

在2000年手機纔剛剛普及的時候,就提出了這麼言簡意賅的跨時代結論,中國最著名的女程序員除了宋丹丹的還有誰!?iphone

ps:喬布斯他就是個買手機的,他懂個錘子的iphone!!!函數

首先話很少,爲了證實宋丹丹所言非虛,一張流程圖足以說明一切:ui

若是看着有點暈,畫出路線圖atom

那麼此次來咱們就看看宋丹丹的「三個思想」中的前兩個吧。spa

1. 瞅瞅你對象佔多大地方 --- instanceSize(size_t extraBytes)

1.1 aligned

曹衝曾說過"大象拉麼大,一個冰箱裝不下」,絕大多數大象都不是一個冰箱能裝下的,那就把大象切了分開多裝幾個冰箱唄。翻譯

下面小學3年級的最後一道應用題:3d

已知,每一個冰箱10平方米,一個大象19平方米。問這個大象裝進冰箱後佔多少平方米?

解:19 ÷ 10 = 1....9(平方米)

∵ 根據題意,大象應該裝2個冰箱

∴ 2 x 10 = 20(平方米)

答:大象裝進冰箱後佔20平方米。

問題是電腦可不知道啥「根據題意」,因此他的算法是:

19 + 10 = 29

而後他再把個位數給抹去

獲得20

這個方法有個弊端<冰箱的大小必定至少要是進制的n冪>,若是十進制,冰箱大小必定要是10,100,1000..... 由於CPU是64位,64/8=8,因此CPU用的是8進制。同理若是是32位則用的是4進制。

這個過程被稱爲<字節對齊>,翻譯成英文就是<aligned>,下面就是這個方法的實現

# define WORD_MASK 7UL
static inline uint32_t word_align(uint32_t x) {
    return (x + WORD_MASK) & ~WORD_MASK;
}
複製代碼

WORD_MASK = 7,7在2進制中等於8

這裏WORD_MASK就是冰箱大小,x就是大象大小,&~WORD_MASK至關於抹去零頭。

1.2 extra

ps: extra也能夠翻譯成益達,沒錯就是那個口香糖。

一頭大象還好,但是我們的app不可能只alloc一個大象吧。因此爲了方便管理,每一個大象裝箱的時候第一個冰箱就放入一個這個大象的檔案袋(<isa>),而不是大象自己。

爲了防止一個裝箱失誤,因此規定就算這個大象就算他啥都沒有(nill),也要給他留個位置。 因此一個大象至少要佔2個冰箱的位置(2*8)16平方米。

有些大象可能還有些特殊狀況要額外天佔用一些空間。下面就是這個方法的實現

size_t instanceSize(size_t extraBytes) {
        size_t size = alignedInstanceSize() + extraBytes;
        if (size < 16) size = 16;
        return size;
    }

uint32_t alignedInstanceSize() {
        return word_align(unalignedInstanceSize());
    }
複製代碼

<unalignedInstanceSize>就是從檔案袋裏讀取大象數據

uint32_t unalignedInstanceSize() {
        assert(isRealized());
        return data()->ro->instanceSize;
    }
複製代碼

如今你把「大象」換成「對象」,「平方米」換成「字節」,是否是很奇妙?

2. 給你對象騰地兒 --- calloc(size_t __count, size_t __size)

2.1 calloc

騰地兒自己沒啥好說的,calloc本是就是庫中的最基本函數。在內存的動態存儲區中分配num個長度爲size的連續空間。num:對象個數,size:對象佔據的內存字節數。可是要注意的是

calloc在動態分配完內存後,自動初始化該內存空間爲零,而malloc不作初始化,分配到的空間中的數據是隨機數據。

size就是咱們上邊算出來的大小

2.2 具體分配

雖然咱們如今知道了cpu是把大象分別放進多個冰箱裏,可是如何分配呢?其實想一想也很簡單,cpu並不會傻到把大象剁成肉臊子,而是把它按照部件一塊一塊而後分別放入冰箱中(畢竟後面還要注入靈魂)。 下面就來證明一下

首先建立一個大象類:

@interface Elephant : NSObject

@property (nonatomic, strong) NSObject *noise;
@property (nonatomic, assign) int head;
@property (nonatomic, copy)   NSString *body;
@property (nonatomic, assign) int tail;
@property (nonatomic, assign) int legs;

@end
複製代碼

而後建立而且賦值

- (void)viewDidLoad {
    [super viewDidLoad];
    Elephant *wildElephant = [[Elephant alloc] init];
    wildElephant.noise = [NSObject new];
    wildElephant.head = 10;
    wildElephant.body = @"bigBody";
    wildElephant.tail = 20;
    wildElephant.legs = 50;
    NSLog(@"%@", wildElephant);
}
複製代碼

咱們來看看手機是怎麼存儲的

第一個 0x0010d800100003dd5 就是咱們所說的isa,佔了整整一個冰箱,徹底如咱們所料。

第二個 0x0000001400000000a 這是兩個小部件(tail 和 head),由於是int類型(佔4字節)就放到了一個冰箱裏。

第三個 0x00000000000000032 這個是腿,也是小部件,可是沒有能夠「湊整」的了,因此雖然小可是仍是佔了一個冰箱。

第四個 0x00006000000109d0 這個就是大部件了,單獨放到一個冰箱裏。

第五個 0x0000000010002018 同第四個。

由此咱們能夠看出來calloc的分配空間仍是很合理的。

下回分解

白雲大媽竟是程序先知,黑土大爺真的一臉懵逼?

注入靈魂究竟從何而來,次幕後是否還另有其人?

敬請期待下回分解。

彩蛋

原本想用《漢尼拔》的人體標原本描述對齊過程的,可是考慮到配圖和你們的心理承受你能力就算了。

相關文章
相關標籤/搜索