Ce que cet article vous apporte concerne le calcul des petites spécifications de mémoire en PHP (exemples de code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Calcul d'allocation de petite mémoire bin_num
Dans le code source PHP, il y a un calcul de spécifications de petite mémoire, spécifiquement dans la fonction zend_mm_small_size_to_bin de Zend/zend_alloc.c, son but est de passer une taille, calculez les spécifications correspondantes. Voir le code :
if (size <= 64) { /* we need to support size == 0 ... */ return (size - !!size) >> 3; } else { t1 = size - 1; t2 = zend_mm_small_size_to_bit(t1) - 3; t1 = t1 >> t2; t2 = t2 - 3; t2 = t2 << 2; return (int)(t1 + t2); }
On voit que ce code est divisé en deux situations à discuter :
1 Le cas où la taille est inférieure ou supérieure. égal à 64 ;
2. Le cas où la taille est supérieure à 64 ;
Analysons ces deux situations en détail ci-dessous.
VoirZEND_MM_BINS_INFO
Cette macro sait que lorsque la taille est inférieure ou égale à 64, elle est une séquence arithmétique, incrémentée de 8, donc utilisez Divisez simplement la taille par 8 (elle est décalée de 3 chiffres vers la droite dans le code source) size >> 3</pre>
<li>
<p>Mais il faut considérer la situation où la taille est égale à 8, 16, etc., donc c'est <code>(size - 1) >> 3
Ensuite il faut considérer le cas de 0, donc le traitement de -1
dans le code source est !!size
, et lorsque la taille est 0, !!0 = 0
. Ainsi lorsque la taille est 0, -1
est converti en -0
, et enfin il y a l'expression dans le code source (size - !!size) >> 3
t1 = size - 1; t2 = zend_mm_small_size_to_bit(t1) - 3; t1 = t1 >> t2; t2 = t2 - 3; t2 = t2 << 2; return (int)(t1 + t2);
Lorsque vous regardez ce code pour la première fois, il est facile de se tromper. Que sont ces t1 t2 ?
Mais n'ayez pas peur, analysons-le étape par étape
/* num, size, count, pages */ #define ZEND_MM_BINS_INFO(_, x, y) \ _( 0, 8, 512, 1, x, y) \ _( 1, 16, 256, 1, x, y) \ _( 2, 24, 170, 1, x, y) \ _( 3, 32, 128, 1, x, y) \ _( 4, 40, 102, 1, x, y) \ _( 5, 48, 85, 1, x, y) \ _( 6, 56, 73, 1, x, y) \ _( 7, 64, 64, 1, x, y) \ _( 8, 80, 51, 1, x, y) \ _( 9, 96, 42, 1, x, y) \ _(10, 112, 36, 1, x, y) \ _(11, 128, 32, 1, x, y) \ _(12, 160, 25, 1, x, y) \ _(13, 192, 21, 1, x, y) \ _(14, 224, 18, 1, x, y) \ _(15, 256, 16, 1, x, y) \ _(16, 320, 64, 5, x, y) \ _(17, 384, 32, 3, x, y) \ _(18, 448, 9, 1, x, y) \ _(19, 512, 8, 1, x, y) \ _(20, 640, 32, 5, x, y) \ _(21, 768, 16, 3, x, y) \ _(22, 896, 9, 2, x, y) \ _(23, 1024, 8, 2, x, y) \ _(24, 1280, 16, 5, x, y) \ _(25, 1536, 8, 3, x, y) \ _(26, 1792, 16, 7, x, y) \ _(27, 2048, 8, 4, x, y) \ _(28, 2560, 8, 5, x, y) \ _(29, 3072, 4, 3, x, y) #endif /* ZEND_ALLOC_SIZES_H */
size = size - 1;
Il s'agit d'une situation limite, similaire à la précédente. De même, la taille qui apparaît plus tard est considérée comme ayant été réduite de un pour le moment
En supposant que ce ne soit pas le cas. regardez ce code source, nous devons trouver le bin_num correspondantZEND_MM_BINS_INFO
On sait de ZEND_MM_BINS_INFO
que les 4 groupes suivants seront ajoutés en tant que groupe, respectivement
2^4, 2^5, 2^6...
Avec ces informations de regroupement, nous devons trouver le bin_num correspondant à siez
pour trouver à quel groupe appartient cette taille
et le décalage de la taille au sein du groupe Quelle est la position de départ du groupe calculé À résoudre
trouver à quelle taille de groupe appartient
64 | 100 0000 80 | 101 0000 96 | 110 0000 112 | 111 0000 128 | 1000 0000 160 | 1010 0000 192 | 1100 0000 224 | 1110 0000 256 | 1 0000 0000 320 | 1 0100 0000 384 | 1 1000 0000 448 | 1 1100 0000 .....
Ensuite, le problème est converti en trouvant le système binaire Le nombre de chiffres du
le plus élevé dans<. 🎜>La solution au code source PHP est donnée ci-dessous. Nous ne l'analyserons pas ici pour le moment. Sachez simplement qu'il renvoie le 1
le plus élevé du binaire
1
1
Calcul du décalage de taille au sein du groupe
int n = 16; if (size <= 0x00ff) {n -= 8; size = size << 8;} if (size <= 0x0fff) {n -= 4; size = size << 4;} if (size <= 0x3fff) {n -= 2; size = size << 2;} if (size <= 0x7fff) {n -= 1;} return n;
(size-64)/16 (size-128)/32 (size-256)/64
, afin que nous puissions obtenir la différence des groupe actuel (16, 32, 64...) en fonction des informations sur le groupe dans lequel il se trouve. 7、8、9...
(size - 2^4 * 4) / 16 = size / 2^4 - 4 (size - 2^5 * 4) / 32 = size / 2^5 - 4 (size - 2^6 * 4) / 64 = szie / 2^6 - 4
7、8、9
Calculez la position de départ du groupe 3
4、5、6
(64-64) / 2^4 = 0
C'est aussi une suite arithmétique, qui est1
6
计算的偏移量是0
计算的起始位置是4*1 + 4 = 8
所以当size=65的bin_num就是起始位置加上偏移量 8 + 0 = 8
我们再看一个size=129的例子
二进制中最高位的1
的位数为8
然后用8减去3得到5
(129 - 1 - 32 * 4) / 64 = 0
偏移量是
计算起始位置是 4 * 2 + 4 = 12
两者相加就是 12 + 0 = 0
size=193
二进制中最高位的1
的位数为8
(193 - 1 - 32 * 4) / 64 = 2
偏移量是
计算起始位置是 4 * 2 + 4 = 12
两者相加就是 12 + 2 = 14
size=1793
二进制中最高位的1
的位数为11
(1793 - 1 - 256 * 4) / 256 = 3
偏移量是
计算起始位置是 4 * 5 + 4 = 24
两者相加就是 24 + 3 = 27
1 t1 = size - 1; 2 t2 = zend_mm_small_size_to_bit(t1) - 3; 3 t1 = t1 >> t2; 4 t2 = t2 - 3; 5 t2 = t2 << 2; 6 return (int)(t1 + t2);
t1 = size - 1;
是为了考虑size为64、128...这些边界情况
t2 = zend_mm_small_size_to_bit(t1) - 3;
这里调用了zend_mm_small_size_to_bit
这个函数,我们看看这个函数
/* higher set bit number (0->N/A, 1->1, 2->2, 4->3, 8->4, 127->7, 128->8 etc) */ int n = 16; if (size <= 0x00ff) {n -= 8; size = size << 8;} if (size <= 0x0fff) {n -= 4; size = size << 4;} if (size <= 0x3fff) {n -= 2; size = size << 2;} if (size <= 0x7fff) {n -= 1;} return n;
看注释我们就知道这个函数是用来返回当前size二进制中最高位1的位数,具体的做法呢其实就是二分法
我们通过zend_mm_small_size_to_bit
这个函数获取了size二进制中最高位1的位数,那么这个 -3
是什么神奇的操作呢
(size - 2^4 * 4) / 16 = size / 2^4 - 4 (size - 2^5 * 4) / 32 = size / 2^5 - 4 (size - 2^6 * 4) / 64 = szie / 2^6 - 4
这里获取二进制的位数是7、8、9...通过 -3
的操作来获取相应的 4、5、6...
上问的分析中提到,我们计算size在组内的偏移量的公式
t1 = t1 >> t2;</pre>
<li><p>把t1右移t2位,这又是什么神奇的操作?</p></li>
<li><p>这里我们把最后计算bin_num的数学公式给写出来,它是等于每组的起始位置加上组内的偏移量</p></li>
<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">binnum = (4n + 4) + (size / 2^n - 4)
binnum = 4n + size / 2^n</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div>
<ul class=" list-paddingleft-2"><li><p>所以第三行的意思我们就知道了,就是size右移2^n次方为</p></li></ul>
<h4>第四行</h4>
<ul class=" list-paddingleft-2">
<li><p><code>t2 = t2 - 3;
这个好理解,可以参照上文得到每组的起始位置的方法
t2 = t2 << 2;
我们再看看bin_num的计算公式
binnum = (4n + 4) + (size / 2^n - 4) binnum = 4n + size / 2^n
那么这行就好理解了,就是计算每组的起始位置4n
对吧,左移两位就是乘以4
return (int)(t1 + t2);
这行没啥说的,就是返回了一个int类型的bin_num
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!