在現代計算架構中,從記憶體中讀取資料,基本上都是按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...