尝试化简php-mm中关于small_bin的index计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include<stdio.h>

int zend_mm_small_size_to_bit(int size){
return (__builtin_clz(size) ^ 0x1f) + 1;
}

int php(int size){
unsigned int t1, t2;

if (size <= 64) {
/* we need to support size == 0 ... */
return (size - !!size) >> 3;
} else {
t1 = size - 1;//311
t2 = zend_mm_small_size_to_bit(t1) - 3;//
t1 = t1 >> t2;
//printf("t1:%d\n",t1);
t2 = t2 - 3;
t2 = t2 << 2;
//printf("t2:%d\n",t2);
return (int)(t1 + t2);
}
}

int my0(int size){
unsigned t1,high,offset;
t1 = size-1;
high = zend_mm_small_size_to_bit(t1)-1;
offset = (t1 - (1<<high) + (1 << (3+high-5))) >> (3+high-5);
//printf("offset:%d\n",offset);
return offset + ((high-4)<<2)-1;
}

int my1(int size){
unsigned t1,high,offset;
t1 = size-1;
high = zend_mm_small_size_to_bit(t1)-1;
offset = (t1 - (1<<high) + (1 << (high-2))) >> (high-2);
//printf("offset:%d\n",offset);
return offset + ((high-4)<<2)-1;
}


int my2(int size){
unsigned t1,high,offset;
t1 = size-1;
high = zend_mm_small_size_to_bit(t1)-3;
offset = (t1 - (1<<(high+2)) + (1 << (high))) >> (high);
//printf("offset:%d\n",offset);
return offset + ((high-2)<<2)-1;
}

int my3(int size){
unsigned t1,high,offset;
t1 = size-1;
high = zend_mm_small_size_to_bit(t1)-3;
offset = ((t1 - (1<<(high+2))) >> (high)) + 1;
//printf("offset:%d\n",offset);
return offset + ((high-2)<<2)-1;
}


int my4(int size){
unsigned t1,high,offset;
t1 = size-1;
high = zend_mm_small_size_to_bit(t1)-3;
offset = ((t1 - (1<<(high+2))) >> (high));
//printf("offset:%d\n",offset);
return offset + ((high-2)<<2);
}


int my5(int size){
unsigned t1,high,offset;
t1 = size-1;
high = zend_mm_small_size_to_bit(t1)-3;
offset = (t1 >> high) -(1<<2) ;
//printf("offset:%d\n",offset);
return offset + ((high-2)<<2);
}


int my6(int size){
unsigned t1,high,offset;
t1 = size-1;
high = zend_mm_small_size_to_bit(t1)-3;
offset = (t1 >> high);
//printf("offset:%d\n",offset);
return offset + ((high-3)<<2);
}


int main(){
/*
8,16,24,32,40,48,56,64 (+8)
80,96,112,128 (16)
160,192,224,256 (32)
320,384,448,512 (64)
640,768,886,1024 (128)
1280,1536,1792,2048 (256)
2560,3072 (512)
*/
printf("%d\n",my6(2600));
printf("%d\n",php(2600));
return 1;
}

small_index在8-64之前按8递增,所以直接除8即可(考虑size==0的情况,!!0==1)

对于t1和t2的我理解是:t1表示区间偏移,t2区间。整体上区间可以划分位(1-64],(64,128],(128,256],(256,512],(512,1024],(1024,2048],(2048,3072]

第一个区间按8划分偏移,第二个区间按16划分偏移,,,,

可以看出来是有规律的,需要申请的内存大小可能落在其中一个区间里面,区间里面在细分。

如果要判断落在那个区间,直觉上要看size最高位的1落在哪个地方,举个例子如果落在2^6上,则一定在(64,128]上(假设已经排除了<=64)。

最高位用bsr算,则为第7bit位,我们需要再算它在这个区间上的偏移,需要先减去前一个区间最大的binsize,然后再除以现区间的划分size。