ビンのインデックスの計算は、想像するより複雑になっています。
なので、ちょこっと説明をさせて頂きますね。
まずインデックスを計算するために必要な環境変数を malloc.c のソースコードを読みながら考えてきましょう。
malloc.c(https://github.com/MacKomatsu/glibc/blob/release/2.27/master/malloc/malloc-internal.h).
54 #ifndef INTERNAL_SIZE_T 55 # define INTERNAL_SIZE_T size_t 56 #endif 57 58 /* The corresponding word size. */ 59 #define SIZE_SZ (sizeof (INTERNAL_SIZE_T))
SIZE_SZ は size_t 型のバイトサイズと同じです。
malloc.c(https://github.com/MacKomatsu/glibc/blob/release/2.27/master/malloc/malloc.c).
1460 #define NBINS 128 1461 #define NSMALLBINS 64 1462 #define SMALLBIN_WIDTH MALLOC_ALIGNMENT 1463 #define SMALLBIN_CORRECTION (MALLOC_ALIGNMENT > 2 * SIZE_SZ) 1464 #define MIN_LARGE_SIZE ((NSMALLBINS - SMALLBIN_CORRECTION) * SMALLBIN_WIDTH) 1465
64 ビットアーキテクチャだと size_t のサイズは 8 バイトになるはずですから MALLOC_ALIGNMENT は 16 となり SIZE_SZ は 8 となりますね。
であれば MIN_LARGE_SIZE は (64 - 0) * 16 = 1024 となります。
32 ビットアーキテクチャだと size_t のサイズは 4 バイトだとして MALLOC_ALIGNMENT は 8 バイトになり SIZE_SZ は 4 になります。
その場合の MIN_LARGE_SIZE は (64 - 0) * 8 = 512 です。
malloc.c(https://github.com/MacKomatsu/glibc/blob/release/2.27/master/malloc/malloc.c).
1466 #define in_smallbin_range(sz) \ 1467 ((unsigned long) (sz) < (unsigned long) MIN_LARGE_SIZE) 1468 1469 #define smallbin_index(sz) \ 1470 ((SMALLBIN_WIDTH == 16 ? (((unsigned) (sz)) >> 4) : (((unsigned) (sz)) >> 3))\ 1471 + SMALLBIN_CORRECTION) 1472
in_smallbin_range は Small bin の範囲内にあるかチェックするマクロです。
つまり 64 ビットアーキテクチャだと 1024 バイトが範囲内となります。
Small Bin か否かは「 sz < MIN_LARGE_SIZE 」の結果によって決定されるってことです。
smallbin_index(sz) は MALLOC_ALIGNMENT が 16 バイトであれば「 sz ÷ 16 」になりますね。
16, 32, 48, 64, …, 1008 バイトてな感じになるはずです。
1008 は 1024 - 16 の意味です。
最大値と一緒になると微妙なので… (´・ω・`)
MALLOC_ALIGNMNET が 8 バイトなら「 sz ÷ 8 」となり、インデックスの間隔がアーキテクチャによって変動します。
16, 24, 32, 40, 48, …, 504 バイトでしょうかね…
最後の値は単に最大値が 512 なので、その直前の 8 の倍数をとっただけです。
これに smallbin_index(sz) を使ってインデックスに翻訳すると 1, 2, 3, …, 63 でしょうかね。
次は Large bin のインデックスの計算を見てみましょう。
malloc.c(https://github.com/MacKomatsu/glibc/blob/release/2.27/master/malloc/malloc.c).
1473 #define largebin_index_32(sz) \ 1474 (((((unsigned long) (sz)) >> 6) <= 38) ? 56 + (((unsigned long) (sz)) >> 6) :\ 1475 ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\ 1476 ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\ 1477 ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\ 1478 ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\ 1479 126) 1480 1481 #define largebin_index_32_big(sz) \ 1482 (((((unsigned long) (sz)) >> 6) <= 45) ? 49 + (((unsigned long) (sz)) >> 6) :\ 1483 ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\ 1484 ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\ 1485 ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\ 1486 ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\ 1487 126) 1488 1489 // XXX It remains to be seen whether it is good to keep the widths of 1490 // XXX the buckets the same or whether it should be scaled by a factor 1491 // XXX of two as well. 1492 #define largebin_index_64(sz) \ 1493 (((((unsigned long) (sz)) >> 6) <= 48) ? 48 + (((unsigned long) (sz)) >> 6) :\ 1494 ((((unsigned long) (sz)) >> 9) <= 20) ? 91 + (((unsigned long) (sz)) >> 9) :\ 1495 ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\ 1496 ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\ 1497 ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\ 1498 126) 1499 1500 #define largebin_index(sz) \ 1501 (SIZE_SZ == 8 ? largebin_index_64 (sz) \ 1502 : MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (sz) \ 1503 : largebin_index_32 (sz)) 1504
それで Large bin のインデックスを計算してくれるマクロは large_bin_index(sz) となります。
64 ビットアーキテクチャだと large_bin_index_64 マクロを実行します。
32 ビットアーキテクチャでアラインメントが 16 バイトなら largebin_index_32_big(sz) をマクロを実行ですね。
最後に 32 ビットアーキテクチャで 16 バイトでないなら largebin_index_32(sz) マクロを使います。
Copyright 2018-2019, by Masaki Komatsu