jemalloc原始碼解讀(四)長度對齊演算法

2021-06-14 20:16:27 字數 3213 閱讀 5875

在現代計算架構中,從記憶體中讀取資料,基本上都是按2^n個位元組來從主存載入cpu中。這個值,基本是cache line的大小。也就是說,如果一塊記憶體是是在同一塊cache line之內是最快的。目前來說,多數pc的cache line值是128個位元組。 對於首位址也是一樣的。在32位機器上,如果有4個位元組的記憶體塊,跨2個cache line,那麼被載入到cpu的時候,需要2次記憶體缺失中斷。

好了,言歸正傳。對於任何一種小記憶體請求,都不會按實際大小分配,首先會按照一定規則進行對齊。這種對齊的規則比較複雜,一般會依照系統頁大小,機器字大小,和系統特性來定製。通常來說,會在不同區間採用不同的步長。舉個例子:

序號大小區間

位元組對齊

0[0--16]81

(16 , 128]162

(128 , 256]323

(256 , 512]64

由於每個區間的步長不一樣,又被劃分成更多的區間。比如(256 , 320]之間長度請求,實際被分配應該是320個位元組,而不是512。而1個位元組的請求,總是被分配8個位元組。

對於任意乙個請求size,為了快速得到他實際應該要被分配的實際長度。這個已經很難通過演算法來完成了,因為這個區間的劃分有一定不確定性,需要根據經驗值來 調整。在jemalloc和tcmalloc他們都採用同樣的演算法,就是二次查表法。首先建立兩個陣列 size_to_index和 class_to_size ,size_to_index儲存class_to_size的下標,而class_to_size儲存對齊後的長度。從jemalloc的size_classes.h和arena.h中挖了一段**出來,稍微修改後,如下:

typedef unsigned char uint8_t ;

#define size_classes \

size_class(0, 8, 8) \

size_class(1, 8, 16) \

size_class(2, 16, 32) \

size_class(3, 16, 48) \

size_class(4, 16, 64) \

size_class(5, 16, 80) \

size_class(6, 16, 96) \

size_class(7, 16, 112) \

size_class(8, 16, 128) \

size_class(9, 32, 160) \

size_class(10, 32, 192) \

size_class(11, 32, 224) \

size_class(12, 32, 256) \

size_class(13, 64, 320) \

size_class(14, 64, 384) \

size_class(15, 64, 448) \

size_class(16, 64, 512) \

size_class(17, 128, 640) \

size_class(18, 128, 768) \

size_class(19, 128, 896) \

size_class(20, 128, 1024) \

size_class(21, 256, 1280) \

size_class(22, 256, 1536) \

size_class(23, 256, 1792) \

size_class(24, 256, 2048) \

size_class(25, 512, 2560) \

size_class(26, 512, 3072) \

size_class(27, 512, 3584) \

#define nbins 28

#define small_maxclass 3584

const uint8_t small_size2bin = ;

typedef struct __arena_bin_info_t arena_bin_info_t ;

arena_bin_info_t arena_bin_info[nbins];

void bin_info_init(void)

void test_size_class()

fclose(file) ;

}void test_reg_size()

fclose(file) ;

}

**中的陣列small_size2bin等價於 size_to_index,arena_bin_info陣列等價於class_to_size。

依據這兩個資料,對於任何乙個長度,要得到對應的對齊長度,就很簡單了,如下:

size_t align(size_t size)

這個演算法是一致的,但是建立class_to_size和size_to_index結果的演算法,卻不一樣。jemalloc用巨集的方式,顯示指定每個區間的步長的。tcmalloc的演算法比較先進,下面是他的演算法,詳細參見gperftools的common.cc檔案的alignmentforsize函式:

1、如果size > maxsize,那麼就以pagesize對齊

2、如果size >= 128 ,從32開始,以2的倍數,增長步長。如下表

序號區間步長0

[128 --> 256)321

[256 --> 512)642

[512 --> 1024)

1283

[1024 --> 2048)

2564

[2048 --> 4096)

5125

[4096 --> 8192)

1024

6[8192 --> 16384)

2048

7[16384 --> 32768)

4096

8[32768 --> 65536)

8192

9[65536 --> 131072)

16384

10[131072 --> 262144)

32768

這種演算法見lgfloor函式,他的主要原則就是保證記憶體浪費利率控制1/8。因此,步長/區間上限=1/8。

3、如果size >= 16,那麼按16對齊

4、小於16就按8對齊。

TestNG原始碼解讀(四)

6.執行testng的一系列操作之執行 run try catch testngexception ex else result.setstatus has failure run方法 run testng.public void run 結束runexecutionlisteners false ...

jieba分詞原始碼解讀四

在上一節中我們考察了結巴分詞對於未登入詞的分詞方法,它使用了hmm模型和用來解碼hmm的維特比演算法。較之基於語料庫打分的初步分詞結果,例句 喬治馬丁寫冰與火之歌拖了好久 分詞情況變成了這樣 喬治 馬丁 寫冰 與 火之歌 拖 了 好久 比原來有改進,但改進幅度可以忽略不計。下一步我們就要除錯 了,目...

openTLD 原始碼解讀

首先是run tld 在其次就是tldexample 最後到了初始化函式tldinit 第乙個比較關鍵的函式 bb scan 將影象網格化,將首先 scale 1.2.10 10 21 個規格 在每個規格上打網格 這個函式有乙個比較重要的方法 ntuples 就是重複 因為網格上的點很多點有相同的x...