Netty源碼解析 -- 內存對齊類SizeClasses

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在學習Netty內存池之前,我們先了解一下Netty的內存對齊類SizeClasses,它爲Netty內存池中的內存塊提供大小對齊,索引計算等服務方法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"源碼分析基於Netty 4.1.52"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Netty內存池中每個內存塊size都符合如下計算公式"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"size = 1 << log2Group + nDelta * (1 << log2Delta)"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"log2Group:內存塊分組"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"nDelta:增量乘數"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"log2Delta:增量大小的log2值"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"SizeClasses初始化後,將計算chunkSize(內存池每次向操作系統申請內存塊大小)範圍內每個size的值,保存到sizeClasses字段中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"sizeClasses是一個表格(二維數組),共有7列,含義如下"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"index:內存塊size的索引"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"log2Group:內存塊分組,用於計算對應的size"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"log2Delata:增量大小的log2值,用於計算對應的size"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"nDelta:增量乘數,用於計算對應的size"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"isMultipageSize:表示size是否爲page的倍數"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"isSubPage:表示是否爲一個subPage類型"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"log2DeltaLookup:如果size存在位圖中的,記錄其log2Delta,未使用"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"sizeClasses負責計算sizeClasses表格"}]},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"private int sizeClasses() {\n int normalMaxSize = -1;\n\n int index = 0;\n int size = 0;\n // #1\n int log2Group = LOG2_QUANTUM;\n int log2Delta = LOG2_QUANTUM;\n int ndeltaLimit = 1 << LOG2_SIZE_CLASS_GROUP;\n\n // #2\n int nDelta = 0;\n while (nDelta < ndeltaLimit) {\n size = sizeClass(index++, log2Group, log2Delta, nDelta++);\n }\n log2Group += LOG2_SIZE_CLASS_GROUP;\n\n // #3\n while (size < chunkSize) {\n nDelta = 1;\n\n while (nDelta <= ndeltaLimit && size < chunkSize) {\n size = sizeClass(index++, log2Group, log2Delta, nDelta++);\n normalMaxSize = size;\n }\n\n log2Group++;\n log2Delta++;\n }\n\n //chunkSize must be normalMaxSize\n assert chunkSize == normalMaxSize;\n\n //return number of size index\n return index;\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"LOG2_QUANTUM=4"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"LOG2"},{"type":"text","marks":[{"type":"italic"}],"text":"SIZE"},{"type":"text","text":"CLASS_GROUP=2"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#1"}]},{"type":"text","text":" log2Group,log2Delta都是從LOG2_QUANTUM開始"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"ndeltaLimit爲2^LOG2"},{"type":"text","marks":[{"type":"italic"}],"text":"SIZE"},{"type":"text","text":"CLASS_GROUP,即內存塊size以4個爲一組進行分組"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#2"}]},{"type":"text","text":" 初始化第0組"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"nDelta從0開始"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"sizeClass方法計算每個size大小"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"注意:第0組後log2Group增加LOG2"},{"type":"text","marks":[{"type":"italic"}],"text":"SIZE"},{"type":"text","text":"CLASS_GROUP,而log2Delta不變"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#3"}]},{"type":"text","text":" 初始化後面的size"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"nDelta從1開始"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每組log2Group+1,log2Delta+1"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"將"},{"type":"codeinline","content":[{"type":"text","text":"log2Group=log2Delta+LOG2_SIZE_CLASS_GROUP"}]},{"type":"text","text":"代入計算公式中,得到"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"size = 1 << (log2Delta+LOG2_SIZE_CLASS_GROUP) + nDelta * (1 << log2Delta)"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"size = (nDelta + 2 ^ LOG2_SIZE_CLASS_GROUP) * (1 << log2Delta)"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"可以看到,每個內存塊size都是(1 << log2Delta)的倍數"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從第二組開始,每組內這個倍數依次是5,6,7,8"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每組內相鄰行大小增量爲(1 << log2Delta),相鄰組之間(1 << log2Delta)翻倍。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Netty默認的配置一個page的大小是2^13,即爲1KB,默認的一個chunk的大小爲16777216,即2MB。sizeClasses表格內存如下:"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/f1/f1a14efc90ed6e76fed02a5a887e26b9.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"size並不是sizeClasses表格的列,這裏爲了直觀而列出。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"Netty內存池中管理了大小不同的內存塊,對於這些不同大小的內存塊,Netty劃分爲不同的等級Small,Normal,Huge"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"sizeClasses表格可以分爲兩部分"}]},{"type":"numberedlist","attrs":{"start":"1","normalizeStart":1},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":1,"align":null,"origin":null},"content":[{"type":"text","text":"isSubPage爲1的size爲Small內存塊,其他爲Normal內存塊,而大於chunkSize的爲huge內存塊,不在表格中。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"分配Small內存塊,需要找到對應的index"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過size2SizeIdx方法計算index"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如需要分配一個360位的內存塊,需要從sizeClasses表格找到第一個大於360的內存塊size,即384,其index爲13"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"numberedlist","attrs":{"start":"2","normalizeStart":"2"},"content":[{"type":"listitem","content":[{"type":"paragraph","attrs":{"indent":0,"number":2,"align":null,"origin":null},"content":[{"type":"text","text":"Normal內存塊必須是page的倍數。"}]}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"將isMultipageSize爲1的行取出組成另一個表格"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/1f/1fba60118098319d57f7af332f57cec7.png","alt":null,"title":"","style":[{"key":"width","value":"100%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"pageIdx並不是sizeClasses表格的列,它是這個新表格的索引。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"PoolChunk中分配Normal內存塊需求查詢對應的pageIdx。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"比如要分配一個50000位的內存塊,需要從這個新表格找到第一個大於50000的內存塊size,即57344,其pageIdx爲6"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"通過pages2pageIdxCompute方法計算pageIdx。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面看一下具體的計算方法"}]},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"public int size2SizeIdx(int size) {\n if (size == 0) {\n return 0;\n }\n // #1\n if (size > chunkSize) {\n return nSizes;\n }\n // #2\n if (directMemoryCacheAlignment > 0) {\n size = alignSize(size);\n }\n // #3\n if (size <= lookupMaxSize) {\n //size-1 / MIN_TINY\n return size2idxTab[size - 1 >> LOG2_QUANTUM];\n }\n // #4\n int x = log2((size << 1) - 1);\n // #5\n int shift = x < LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM + 1\n ? 0 : x - (LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM);\n\n int group = shift << LOG2_SIZE_CLASS_GROUP;\n // #6\n int log2Delta = x < LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM + 1\n ? LOG2_QUANTUM : x - LOG2_SIZE_CLASS_GROUP - 1;\n // #7\n int deltaInverseMask = -1 << log2Delta;\n int mod = (size - 1 & deltaInverseMask) >> log2Delta &\n (1 << LOG2_SIZE_CLASS_GROUP) - 1;\n\n return group + mod;\n}"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#1"}]},{"type":"text","text":" 大於chunkSize,就是返回nSizes代表申請的是Huge內存塊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#2"}]},{"type":"text","text":" 不使用sizeClasses表格,將申請內存大小轉換爲directMemoryCacheAlignment的倍數,directMemoryCacheAlignment默認爲0。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#3"}]},{"type":"text","text":" SizeClasses將一部分較小的size與對應index記錄在size2idxTab作爲位圖,這裏直接查詢size2idxTab,避免重複計算"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"size2idxTab中保存了(size-1)/(2^LOG2_QUANTUM) --> idx的對應關係。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#4"}]},{"type":"text","text":" 對申請內存大小進行log2的向上取整,就是每組最後一個內存塊size。-1是爲了避免申請內存大小剛好等於2的指數次冪時被翻倍。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"將"},{"type":"codeinline","content":[{"type":"text","text":"log2Group = log2Delta + LOG2_SIZE_CLASS_GROUP"}]},{"type":"text","text":","},{"type":"codeinline","content":[{"type":"text","text":"nDelta=2^LOG2_SIZE_CLASS_GROUP"}]},{"type":"text","text":"代入計算公式,可得"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"lastSize = 1 << (log2Group + 1)"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"即"},{"type":"codeinline","content":[{"type":"text","text":"x = log2Group + 1"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#5"}]},{"type":"text","text":" shift, 當前在第幾組,從0開始(sizeClasses表格中0~3行爲第0組,4~7行爲第1組,以此類推,不是log2Group)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"x < LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM + 1"}]},{"type":"text","text":",即"},{"type":"codeinline","content":[{"type":"text","text":"log2Group < LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM "}]},{"type":"text","text":",滿足該條件的是第0組的size,這時shift固定是0。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"從sizeClasses方法可以看到,除了第0組,都滿足"},{"type":"codeinline","content":[{"type":"text","text":"shift = log2Group - LOG2_QUANTUM - (LOG2_SIZE_CLASS_GROUP - 1)"}]},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"shift << LOG2_SIZE_CLASS_GROUP"}]},{"type":"text","text":"就是該組第一個內存塊size的索引"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#6"}]},{"type":"text","text":" 計算log2Delta"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第0組固定是LOG2_QUANTUM"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"除了第0組,將"},{"type":"codeinline","content":[{"type":"text","text":"nDelta = 2^LOG2_SIZE_CLASS_GROUP"}]},{"type":"text","text":"代入計算公式"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"lastSize = ( 2^LOG2_SIZE_CLASS_GROUP + 2^LOG2_SIZE_CLASS_GROUP ) * (1 << log2Delta)"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"lastSize = (1 << log2Delta) << LOG2_SIZE_CLASS_GROUP << 1"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"#7"}]},{"type":"text","text":" 前面已經定位到第幾組了,下面要找到申請內存大小應分配在該組第幾位"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏要找到比申請內存大的最小size。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"申請內存大小可以理解爲上一個size加上一個不大於(1 << log2Delta)的值,即"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"(nDelta - 1 + 2^LOG2_SIZE_CLASS_GROUP) * (1 << log2Delta) + n"}]},{"type":"text","text":", 備註:0 < n <= (1 << log2Delta)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"nDelta - 1就是mod"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"& deltaInverseMask"}]},{"type":"text","text":",將申請內存大小最後log2Delta個bit位設置爲0,可以理解爲減去n"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":">> log2Delta"}]},{"type":"text","text":",右移log2Delta個bit位,就是除以(1 << log2Delta),結果就是(nDelta - 1 + 2 ^ LOG2"},{"type":"text","marks":[{"type":"italic"}],"text":"SIZE"},{"type":"text","text":"CLASS_GROUP)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"& (1 << LOG2_SIZE_CLASS_GROUP) - 1"}]},{"type":"text","text":", 取最後的LOG2"},{"type":"text","marks":[{"type":"italic"}],"text":"SIZE"},{"type":"text","text":"CLASS_GROUP個bit位的值,結果就是mod"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"size - 1"}]},{"type":"text","text":",是爲了申請內存等於內存塊size時避免分配到下一個內存塊size中,即n == (1 << log2Delta)的場景。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"疑問:既然右移log2Delta個bit位,那爲什麼前面要將log2Delta個bit位設置爲0?"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"第0組由於log2Group等於log2Delta,代入計算公式如下"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"1 << log2Delta + (nDelta - 1) * (1 << log2Delta) + n"}]},{"type":"text","text":", 備註:0 < n <= (1 << log2Delta)"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"codeinline","content":[{"type":"text","text":"nDelta * (1 << log2Delta) + n"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"所以第0組nDelta從0開始,mod = nDelta"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"pages2pageIdxCompute方法計算pageIdx邏輯與size2SizeIdx方法類似,只是將LOG2_QUANTUM變量換成了pageShifts,這裏不再重複。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"SizeClasses是給PoolArena(內存池),PoolChunk(內存塊)提供服務的,建議大家結合後面分析PoolArena,PoolChunk的文章一起理解。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果大家對SizeClasses具體算法不感興趣,只有理解SizeClasses類中利用sizeClasses表格,爲PoolArena,PoolChunk提供計算index,pageIdx索引的方法,也可以幫助大家理解後面解析PoolArena,PoolChunk的文章。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"下面貼出sizeClasses完整表格(可複製到Excle,以|分列)"}]},{"type":"codeblock","attrs":{"lang":""},"content":[{"type":"text","text":"| index | log2Group | log2Delta | nDelta | isMultiPageSize | isSubPage | log2DeltaLookup | size |\n| 0 | 4 | 4 | 0 | 0 | 1 | 4 | 16 -- 2B |\n| 1 | 4 | 4 | 1 | 0 | 1 | 4 | 32 -- 4B |\n| 2 | 4 | 4 | 2 | 0 | 1 | 4 | 48 -- 6B |\n| 3 | 4 | 4 | 3 | 0 | 1 | 4 | 64 -- 8B |\n| 4 | 6 | 4 | 1 | 0 | 1 | 4 | 80 -- 10B |\n| 5 | 6 | 4 | 2 | 0 | 1 | 4 | 96 -- 12B |\n| 6 | 6 | 4 | 3 | 0 | 1 | 4 | 112 -- 14B |\n| 7 | 6 | 4 | 4 | 0 | 1 | 4 | 128 -- 16B |\n| 8 | 7 | 5 | 1 | 0 | 1 | 5 | 160 -- 20B |\n| 9 | 7 | 5 | 2 | 0 | 1 | 5 | 192 -- 24B |\n| 10 | 7 | 5 | 3 | 0 | 1 | 5 | 224 -- 28B |\n| 11 | 7 | 5 | 4 | 0 | 1 | 5 | 256 -- 32B |\n| 12 | 8 | 6 | 1 | 0 | 1 | 6 | 320 -- 40B |\n| 13 | 8 | 6 | 2 | 0 | 1 | 6 | 384 -- 48B |\n| 14 | 8 | 6 | 3 | 0 | 1 | 6 | 448 -- 56B |\n| 15 | 8 | 6 | 4 | 0 | 1 | 6 | 512 -- 64B |\n| 16 | 9 | 7 | 1 | 0 | 1 | 7 | 640 -- 80B |\n| 17 | 9 | 7 | 2 | 0 | 1 | 7 | 768 -- 96B |\n| 18 | 9 | 7 | 3 | 0 | 1 | 7 | 896 -- 112B |\n| 19 | 9 | 7 | 4 | 0 | 1 | 7 | 1024 -- 128B |\n| 20 | 10 | 8 | 1 | 0 | 1 | 8 | 1280 -- 160B |\n| 21 | 10 | 8 | 2 | 0 | 1 | 8 | 1536 -- 192B |\n| 22 | 10 | 8 | 3 | 0 | 1 | 8 | 1792 -- 224B |\n| 23 | 10 | 8 | 4 | 0 | 1 | 8 | 2048 -- 256B |\n| 24 | 11 | 9 | 1 | 0 | 1 | 9 | 2560 -- 320B |\n| 25 | 11 | 9 | 2 | 0 | 1 | 9 | 3072 -- 384B |\n| 26 | 11 | 9 | 3 | 0 | 1 | 9 | 3584 -- 448B |\n| 27 | 11 | 9 | 4 | 0 | 1 | 9 | 4096 -- 512B |\n| 28 | 12 | 10 | 1 | 0 | 1 | 0 | 5120 -- 640B |\n| 29 | 12 | 10 | 2 | 0 | 1 | 0 | 6144 -- 768B |\n| 30 | 12 | 10 | 3 | 0 | 1 | 0 | 7168 -- 896B |\n| 31 | 12 | 10 | 4 | 1 | 1 | 0 | 8192 -- 1.0KB |\n| 32 | 13 | 11 | 1 | 0 | 1 | 0 | 10240 -- 1.25KB |\n| 33 | 13 | 11 | 2 | 0 | 1 | 0 | 12288 -- 1.5KB |\n| 34 | 13 | 11 | 3 | 0 | 1 | 0 | 14336 -- 1.75KB |\n| 35 | 13 | 11 | 4 | 1 | 1 | 0 | 16384 -- 2.0KB |\n| 36 | 14 | 12 | 1 | 0 | 1 | 0 | 20480 -- 2.5KB |\n| 37 | 14 | 12 | 2 | 1 | 1 | 0 | 24576 -- 3.0KB |\n| 38 | 14 | 12 | 3 | 0 | 1 | 0 | 28672 -- 3.5KB |\n| 39 | 14 | 12 | 4 | 1 | 0 | 0 | 32768 -- 4.0KB |\n| 40 | 15 | 13 | 1 | 1 | 0 | 0 | 40960 -- 5.0KB |\n| 41 | 15 | 13 | 2 | 1 | 0 | 0 | 49152 -- 6.0KB |\n| 42 | 15 | 13 | 3 | 1 | 0 | 0 | 57344 -- 7.0KB |\n| 43 | 15 | 13 | 4 | 1 | 0 | 0 | 65536 -- 8.0KB |\n| 44 | 16 | 14 | 1 | 1 | 0 | 0 | 81920 -- 10.0KB |\n| 45 | 16 | 14 | 2 | 1 | 0 | 0 | 98304 -- 12.0KB |\n| 46 | 16 | 14 | 3 | 1 | 0 | 0 | 114688 -- 14.0KB |\n| 47 | 16 | 14 | 4 | 1 | 0 | 0 | 131072 -- 16.0KB |\n| 48 | 17 | 15 | 1 | 1 | 0 | 0 | 163840 -- 20.0KB |\n| 49 | 17 | 15 | 2 | 1 | 0 | 0 | 196608 -- 24.0KB |\n| 50 | 17 | 15 | 3 | 1 | 0 | 0 | 229376 -- 28.0KB |\n| 51 | 17 | 15 | 4 | 1 | 0 | 0 | 262144 -- 32.0KB |\n| 52 | 18 | 16 | 1 | 1 | 0 | 0 | 327680 -- 40.0KB |\n| 53 | 18 | 16 | 2 | 1 | 0 | 0 | 393216 -- 48.0KB |\n| 54 | 18 | 16 | 3 | 1 | 0 | 0 | 458752 -- 56.0KB |\n| 55 | 18 | 16 | 4 | 1 | 0 | 0 | 524288 -- 64.0KB |\n| 56 | 19 | 17 | 1 | 1 | 0 | 0 | 655360 -- 80.0KB |\n| 57 | 19 | 17 | 2 | 1 | 0 | 0 | 786432 -- 96.0KB |\n| 58 | 19 | 17 | 3 | 1 | 0 | 0 | 917504 -- 112.0KB |\n| 59 | 19 | 17 | 4 | 1 | 0 | 0 | 1048576 -- 128.0KB |\n| 60 | 20 | 18 | 1 | 1 | 0 | 0 | 1310720 -- 160.0KB |\n| 61 | 20 | 18 | 2 | 1 | 0 | 0 | 1572864 -- 192.0KB |\n| 62 | 20 | 18 | 3 | 1 | 0 | 0 | 1835008 -- 224.0KB |\n| 63 | 20 | 18 | 4 | 1 | 0 | 0 | 2097152 -- 256.0KB |\n| 64 | 21 | 19 | 1 | 1 | 0 | 0 | 2621440 -- 320.0KB |\n| 65 | 21 | 19 | 2 | 1 | 0 | 0 | 3145728 -- 384.0KB |\n| 66 | 21 | 19 | 3 | 1 | 0 | 0 | 3670016 -- 448.0KB |\n| 67 | 21 | 19 | 4 | 1 | 0 | 0 | 4194304 -- 512.0KB |\n| 68 | 22 | 20 | 1 | 1 | 0 | 0 | 5242880 -- 640.0KB |\n| 69 | 22 | 20 | 2 | 1 | 0 | 0 | 6291456 -- 768.0KB |\n| 70 | 22 | 20 | 3 | 1 | 0 | 0 | 7340032 -- 896.0KB |\n| 71 | 22 | 20 | 4 | 1 | 0 | 0 | 8388608 -- 1.0MB |\n| 72 | 23 | 21 | 1 | 1 | 0 | 0 | 10485760 -- 1.25MB |\n| 73 | 23 | 21 | 2 | 1 | 0 | 0 | 12582912 -- 1.5MB |\n| 74 | 23 | 21 | 3 | 1 | 0 | 0 | 14680064 -- 1.75MB |\n| 75 | 23 | 21 | 4 | 1 | 0 | 0 | 16777216 -- 2.0MB |"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果您覺得本文不錯,歡迎關注我的微信公衆號,您的關注是我堅持的動力!"}]},{"type":"image","attrs":{"src":"https://static001.geekbang.org/infoq/da/da6c5c8363dc2a6fc148bc2eab39d883.jpeg","alt":null,"title":"","style":[{"key":"width","value":"50%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章