php中small記憶體規格的計算(程式碼範例)
這篇文章帶給大家的內容是關於php中small記憶體規格的計算(程式碼範例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
small記憶體分配計算bin_num
在PHP原始碼中,有一段對small記憶體規格的計算,具體在Zend/zend_alloc.c的zend_mm_small_size_to_bin函數中,其目的是傳入一個size ,計算對應的規格。見程式碼:
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); }
可以看出,這段程式碼中分為兩種情況來討論:
1、size小於等於64的情況;
2、size大於64的情況;
在下面我們對這兩種情況詳細分析下。
對於size小於等於64的情況
看
ZEND_MM_BINS_INFO
這個巨集知道當size小於等於64的情況是等差數列,遞增8,所以使用size除以8就行(源碼中是右移3位)size >> 3</pre> <li><p>但是要考慮到size等於8、 16等的情況,所以為<code>(size - 1) >> 3
然後要考慮到為0的情況,所以原始碼中對於
-1
的處理是!!size
,當size為0的情況!!0 = 0
。所以當size為0的情況就把-1
轉換成了-0
,最後有了原始碼中的表達式(size - !!size) >> ; 3
- ##初看這個程式碼,容易一臉懵逼,這些t1 t2 都是啥啊
- #不過不用怕,我們一點點來分析 ##步驟分析
- size = size - 1;
這個是邊界情況,跟前面一樣,後面出現的size暫且都認為已近減一了
#假設不看這個原始碼,我們要實作在 - ZEND_MM_BINS_INFO
中找到對應的bin_num
##由 ZEND_MM_BINS_INFO - 得知後續的增加4個為一組,分別為
2^4, 2^5, 2^6...
登入後複製 - 找到這個size屬於哪一組
- 並且size在群組內的偏移量是多少
- 計算組的起始位置
- 那現在問題轉換成了上面3個小問題,我們一個一個來解決
- 找到size屬於哪一組
- 我們看十進位看不出來什麼名堂,就把這些值轉成二進位看看吧
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 .....
登入後複製- 那就是說我們可以計算二進制的長度來決定它的分組,那麼二進制的長度又是啥呢,其實就是當前二進制的最高位為 1
- 的位數
1##那麼問題又轉換成了求二進位中最高位元的
的位元數
1下面給出php原始碼的解法,這裡暫時不對其解析,只要知道它傳回的是二進位中最高位的
的位數<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">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;</pre><div class="contentsignin">登入後複製</div></div>
#假設我們申請的size為65,那麼這裡的n回傳7計算size在群組內的偏移量
#現在來看看上一個步驟中的回傳的值,每個組分別是
,那我們現在來看看這樣的資料怎麼計算組內的偏移量<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">(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</pre><div class="contentsignin">登入後複製</div></div>
那是不是可以用- 3
得到
4、5、6
,這樣我們就可以根據它在哪一組的資訊來得到目前組的差值(16、32、64...) (64-64) / 2^4 = 0
登入後複製計算群組的起始位置
那是不是就是用最高位的
1 的位數減去- 6
就可以得到分組資訊了
得到分組資訊之後,怎麼知道每組的起始位置呢
- ##我們知道起始位置分別是
8、12、16...
它也是一個等差數列,就是 4n 4 我們在看看size=65的那個例子
计算的偏移量是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
t1 = size - 1;
是为了考虑size为64、128...这些边界情况
t2 = zend_mm_small_size_to_bit(t1) - 3;
这里调用了
zend_mm_small_size_to_bit
这个函数,我们看看这个函数看注释我们就知道这个函数是用来返回当前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">登入後複製</div></div><div class="contentsignin">登入後複製</div></div> <ul class=" list-paddingleft-2"><li><p>所以第三行的意思我们就知道了,就是size右移2^n次方为</p></li></ul> <h4 id="第四行">第四行</h4> <ul class=" list-paddingleft-2"> <li><p><code>t2 = t2 - 3;
这个好理解,可以参照上文得到每组的起始位置的方法
t2 = t2 << 2;
我们再看看bin_num的计算公式
那么这行就好理解了,就是计算每组的起始位置
4n
对吧,左移两位就是乘以4return (int)(t1 + t2);
这行没啥说的,就是返回了一个int类型的bin_num
對於size大於64的情況
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);
初始懵逼
/* 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減去每組的起始siez大小然後除以目前群組內的差值(16、32、64...)即可,也就是
(size-64)/16 (size-128)/32 (size-256)/64- 減去
現在我們有了偏移量的信息,假定我們分組是1、2、3
代码分析
php实现代码
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);
第一行
第二行
/* 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;
第三行
第五行
binnum = (4n + 4) + (size / 2^n - 4) binnum = 4n + size / 2^n
第六行
以上是php中small記憶體規格的計算(程式碼範例)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。
