37.1. 32 ビットアーキテクチャのビン

 まずは見本として largebin_index_32(sz) を見てみましょうかね。

1473 #define largebin_index_32(sz)                                                \
1474   (((((unsigned long) (sz)) >> 6) <= 38) ?  56 + (((unsigned long) (sz)) >> 6) :\

 まずはソースコード内のコメントにあるように 64 バイト間隔のビンは 32 個あるとします。

 64 バイトのビンの開始サイズは 512 なので開始インデックスは 56 + (512 >> 6) = 56 + 8 = 64 です。

 32 ビンあるのであれば 2560 になるはずです。

 しかしながら式を信じるなら最大値は 64 * 38 = 2432 となってしまいます。

1475    ((((unsigned long) (sz)) >> 9) <= 20) ?  91 + (((unsigned long) (sz)) >> 9) :\

 この場合 sz を 512 の倍数とするなら、開始点を2432 とするのは半端なので近似する倍数は 512 × 5 = 2560 となります。

 実際この近似をしないとビンの数は 30 となり必要に満たないです。

 2560 を上限値にする場合のインデックスは以下のように展開できます。

表37.1 64 バイト間隔のインデックス

インデックス
64     
 65     
 66     
 67  
 ....
 94       
 95
バイトサイズ
512-575
 576-639
 640-703
 704-
 ....
 2432-2495
 2496-2559

 このように 64 バイト間隔と 512 バイト間隔から、バイトサイズによって算出されるインデックスがなんとなく推定できます。

 面倒なことにインデックス 95 は 1474 行ではなく 1475 行から類推されます。

 なぜかというと 1475 行の式から 2559 >> 9 = 4 となるので、91 + (2559 >> 9) = 95 が算出されるからです。

 512 バイト間隔のビンの開始サイズは 2560 なので、開始インデックスは 91 + (2560 >> 9) = 91 + 5 = 96 となります。

 上限値は式から 512 * 20 = 10240 となります。

 では 4096 バイト間隔のインデックス算出式はどうでしょうかね?

1476    ((((unsigned long) (sz)) >> 12) <= 10) ? 110 + (((unsigned long) (sz)) >> 12) :\

 1476 行では 4096 バイト間隔のビンのインデックスを算出するのですが、10240 というのはあまり

 10240 は 4096 の倍数としては端数になってしまうため、キリの良い値は 12288 となります。

表37.2 512 バイト間隔のインデックス

インデックス96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 (111)
バイトサイズ
2560-3071
 3072-3583
 3584-4095
 4096-5129
 5120-5631
 5632-6143
 6144-6655 
 6656-7167
7168-7679
7680-8191
8192-8703
8704-9215
9216-9727
9728-10239
10240
(10752)

 式によるとインデックス 111 は飛び地となるようですね。

 10240 が上限値なので、上限値を超えた 10752 は 512 間隔のビンには適用できないサイズだからです。

 つまり (10752 >> 9) は 21 となりますので、条件式「 ⇐ 20 」で偽を返すため 1475 行の式は 1475 行の式の評価に移ります。

 10752 で開始インデックスを計算すると以下のように値は 112 となります。

 110 + (10752 >> 12) = 112

 てなことでインデックス 111 で飛び地ができてるっぽいです。

 まあ飛び地といっても 100 の次がインデックス 112 になるってだけのことなんですがね。

 繰り返しになりますが 4096 バイト間隔のビンの開始サイズは 10240 なので 110 + (10240 >> 12) = 110 + 2 = 112 になります。

 1476 行の式により上限値は 4096 * 10 = 40960 になります。

 次は 1477 行の式です。

1477    ((((unsigned long) (sz)) >> 15) <= 4) ? 119 + (((unsigned long) (sz)) >> 15) :\

 1477 行は 32768 バイトのビンのインデックスを返します。

 40960 は 32768 の倍数としては端数になるため 65536 を最大値として補正すると言いたいところですが、110 と 111 が飛び地になるのは仕方ないと諦めるしかなさそうです。

 まあ筆者が間違ってるだけかも知らんですけどね… (´・ω・`)

表37.3 4096 バイト間隔のインデックス

インデックス112113114115116117118119
バイトサイズ
10240-12287
12288-16383
16384-20479
20480-24575
24576-28671
28672-32767
32768-36863
36864-40959

 これも強引に表にしちゃってます。

 まあ 1476 行の式によると 40960 を超えたら 1477 行の処理に移るのでインデックス 120 はそちらで算出できます。

119 + (40960 >> 15) = 120 + 1 = 120

 よって、この場合の開始地点は 40960 とすれば良いでしょう。

 例のように上限値は 32768 * 4 = 131072 になります。

次は 1478 行の式です。
1478    ((((unsigned long) (sz)) >> 18) <= 2) ? 124 + (((unsigned long) (sz)) >> 18) :\

 1478 行は 262144 バイトのビンのインデックスを算出します。

 ちなみに 131072 は 262144 の丁度半分になります。

 まあ 2 の倍数同士なんで、こういうこともあります… (´・ω・`)

 それで 1477 行の 32768 バイトのビンは以下のようになるはずです。

表37.4 32768 バイト間隔のインデックス

インデックス120 121 122 123 (124)
バイトサイズ
40960-73727
73728-106495
106496-131071
131072  
163840

 1477 行の式によると 32768 * 4 = 131072 を超えると 1478 行に処理が移ります。

 1478 行のオフセットは 124 になってるのですが 131072 は 262144 に比べると端数に過ぎません。

 てなことで 131072 をビンの開始地点とするのであれば 124 + (131072 >> 18) = 124 + 0 = 124 とインデックスを計算dけいます。

 最後に 1478 行の 262144 のビンのインデックスは以下のようになるはずです。

表37.5 262144 バイト間隔のインデックス

インデックス124 125 (126)
バイトサイズ
131073-262143
262144-524287 
 (524288-)

 1478行の式から最大値は 262144 * 2 = 524288 となります。

 あとはそれ以外のインデックスは 1 個しかないです。

1479    126)

この 126 は 524288 以上になりますんで、ビンがキャッシュするチャンクのサイズはかなり巨大になってます。

Copyright 2018-2019, by Masaki Komatsu