malloc的原始碼剖析源

2021-04-17 15:43:01 字數 4438 閱讀 8229

對malloc的原始碼剖析源於我自己實現的共享記憶體分配器,使用buddy演算法和紅黑樹結構實現對共享記憶體的分配**管理,對其效能進行測試的時候,發現效能只有malloc的1/3~1/2,原本以為自己的實現效能應該比malloc高的,結果出乎意外,這讓我產生窺探dlmalloc原始碼的好奇心,為此,找到http: //www.malloc.de/malloc/ptmalloc2.tar.gz的源**進行分析,該版本在多執行緒環境中其效能較高,具體見裡面的readme說明

先拿到malloc入手,去除不必要的巨集,其原始碼如下

void* malloc(size_t bytes)

else

#endif

}

if(!victim) return 0;

} else

(void)mutex_unlock(&ar_ptr->mutex);

return chunk2mem(victim); // 將chunk轉換成指標

}

從上面的原始碼知,malloc的實現很簡單:

1、根據請求的bytes大小進行調整

2、獲取適當的arena

3、從arena中獲取chunk

下面看一下幾個重要的巨集及函式

// pad request bytes into a usable size, return non-zero on overflow

// 對req增加必要的cookie資訊所需要的長度然後進行對齊,當溢位時返回1

#define request2size(req, nb) /

((nb = (req) + (size_sz + malloc_align_mask)),/

((long)nb <= 0 || nb < (internal_size_t) (req) /

? (__set_errno (enomem), 1) /

: ((nb < (minsize + malloc_align_mask) /

? (nb = minsize) : (nb &= ~malloc_align_mask)), 0)))

// 獲取arena並對其上鎖,首先查詢被該執行緒所占用的arena,如果獲取不到,則對arena鍊錶進行搜尋,如果仍沒有可用的arean,則建立乙個新的,建立新的arena時,第二個引數只是用於提示新的arena需要立即分配多大的空間

#define arena_get(ptr, size) do else /

ptr = arena_get2(ptr, (size)); /

} while(0)

arena_get2從迴圈的arena鍊錶中找合適的arena,如果沒有找到,則建立新的arena

static arena * internal_function arena_get2(arena *a_tsd, size_t size)

}

// 從arena迴圈鍊錶中搜尋可用的arena

repeat:

do

a = a->next;

} while(a != a_tsd);

// 從arena迴圈鍊錶中仍沒有找到可用的arena,如果不能獲得list_lock,則重新嘗試

if(mutex_trylock(&list_lock))

(void)mutex_unlock(&list_lock);

// 沒有現成可用的arena,所以建立乙個新的arena

// 首先是建立乙個heap

h = new_heap(size + (sizeof(*h) + sizeof(*a) + malloc_alignment));

if(!h)

// 初始化heap的arena資訊

a = h->ar_ptr = (arena *)(h+1);

for(i=0; inext = null;

a->size = h->size;

arena_mem += h->size;

// 初始化該heap的mutex, lock mutex

tsd_setspecific(arena_key, (void_t *)a);

mutex_init(&a->mutex);

i = mutex_lock(&a->mutex); /* remember result */

// 設定heap的第乙個chunk,並且要正確地對齊

ptr = (char *)(a + 1);

misalign = (unsigned long)chunk2mem(ptr) & malloc_align_mask;

if (misalign > 0)

ptr += malloc_alignment - misalign;

top(a) = (mchunkptr)ptr;

set_head(top(a), (((char*)h + h->size) - ptr) | prev_inuse);

// 把新的arena新增到arena鍊錶中

(void)mutex_lock(&list_lock);

a->next = main_arena.next;

main_arena.next = a;

(void)mutex_unlock(&list_lock);

if(i) /* locking failed; keep arena for further attempts later */

return 0;

thread_stat(++(a->stat_lock_loop));

return a;

}

static mchunkptr internal_function chunk_alloc(arena *ar_ptr, internal_size_t nb)

if (victim != q) // 從bin中獲取到chunk,返回

// 從上面的兩個bin中沒有找到合適的chunk,則需要從其餘的bin中進行查詢

idx += 2;

}

else

else if (remainder_size >= 0) // 完全匹配

}

++idx;

}

// 利用上次拆分剩餘的chunk

if ( (victim = last_remainder(ar_ptr)->fd) != last_remainder(ar_ptr))

// 上次拆分剩餘的chunk的大小正好合適,把該chunk分配出去,把它從remainder鍊錶中去掉

clear_last_remainder(ar_ptr);

if (remainder_size >= 0) // remainder鍊錶不為空,則簡單把拆分後剩下的chunk進行設定

// 否則需要把拆分後剩下的chunk放到remainder鍊錶中

frontlink(ar_ptr, victim, victim_size, remainder_index, bck, fwd);

}

// 如果還有可能的非空並且足夠大的塊,從其它bin中進行查詢最匹配的chunk

if ( (block = idx2binblock(idx)) <= binblocks(ar_ptr))

}

// 對每乙個可能的非空塊

for (;;)

else if (remainder_size >= 0) // 使用該chunk

}

bin = next_bin(bin);

} while ((++idx & (binblockwidth - 1)) != 0);

// 清除block標識位

do

--startidx;

q = prev_bin(q);

} while (first(q) == q);

// 獲取下乙個可能的非空塊

if ( (block <<= 1) <= binblocks(ar_ptr) && (block != 0) )

}

else

break;

}

}

// 嘗試使用top chunk,要求要有乙個remainder,從而確保top總是存在的

if ( (remainder_size = chunksize(top(ar_ptr)) - nb) < (long)minsize)

victim = top(ar_ptr);

set_head(victim, nb | prev_inuse);

top(ar_ptr) = chunk_at_offset(victim, nb);

set_head(top(ar_ptr), remainder_size | prev_inuse);

check_malloced_chunk(ar_ptr, victim, nb);

return victim;

}

原始碼剖析 Hashtable 原始碼剖析

hashtable同樣是基於雜湊表實現的,同樣每個元素都是key value對,其內部也是通過單鏈表解決衝突問題,容量不足 超過了閾值 時,同樣會自動增長。hashtable也是jdk1.0引入的類,是執行緒安全的,能用於多執行緒環境中。hashtable同樣實現了serializable介面,它支...

python原始碼剖析 Python原始碼剖析

第頁共 頁python 原始碼剖析 物件機制 1.物件 在python 的世界中,一切都是物件,乙個整數是乙個物件,乙個字串也是 乙個物件,更為奇妙的是,型別也是乙個物件,整數型別是乙個物件,字串類 型也是乙個物件。從 年guido 在那個聖誕節揭開 python 世界的大幕開始,一直到現在,pyt...

Erlang hotwheels原始碼剖析

整體構架 janus transport sup 實質為transport,supervisor,client instance supervisor 每個tcp會話建立乙個transport程序來處理對應客戶端的請求。janus topman sup 實質為topman,worker,topic ...