百度工程師講PHP函數的實現原理及效能分析(二)_PHP

來源:互聯網
上載者:User
關鍵字 百度 工程師 PHP函數 實現原理
類方法
類方法其執行原理和使用者函數是相同的,也是翻譯成opcodes順次調用。類的實現,zend用一個資料結構zend_class_entry來實現,裡面儲存了類相關的一些基本資料。這個entry是在php編譯的時候就已經處理完成。
在 zend_function的common中,有一個成員叫做scope,其指向的就是當前方法對應類的zend_class_entry。關於php中物件導向的實現,這裡就不在做更詳細的介紹,今後將專門寫一篇文章來詳述php中物件導向的實現原理。就函數這一塊來說,method實現原理和 function完全相同,理論上其效能也差不多,後面我們將做詳細的效能對比。

效能對比
函數名長度對效能的影響

》》測試方法 對名字長度為1、2、4、8、16的函數進行比較,測試比較它們每秒可執行次數,確定函數名長度對效能的影 響

》》測試結果如

》》結果分析
從圖上可以看出,函數名的長度對效能還是會有一定的影響。一個長度為1的函數和長度為16的 空函數調用 ,其效能差了1倍。分析一下源碼不難找到原因,如前面敘述所說,函數調用的時候zend會先在一個全域的funtion_table中通過函數名查詢相關資訊,function_table是一個雜湊表。必然的,名字越長查詢所需要的時間就越多。 因此,在實際編寫程式的時候,對多次調用的函數,名字建議不要太長。

雖然函數名長度對效能有一定影響,但具體有多大呢?這個問題應該還是需要結合實際情況來考慮,如果一個函數本身比較複雜的話,那麼對整體的效能影響並不大。一個建議是對於那些會調用很多次,本身功能又比較簡單的函數,可以適當取一些言簡意賅的名字。
函數個數對效能的影響

》》測試方法
在以下三種環境下進行函數調用測試,分析結果:1.程式僅包含1個函數 2.程式包含100個函數 3.程式包含1000個函數。測試這三種情況下每秒所能調用的函數次數

》》測試結果如

》》結果分析
從測試結果可以看出,這三種情況下效能幾乎相同,函數個數增加時效能下降微乎其微,可以忽略。從實現原理分析,幾種實現下唯一的區別在於函數擷取的部分。如前文所述,所有的函數都放在一個hash表中,在不同個數下尋找效率都應該還是接近於O(1),所以效能差距不大。
不同類型函數調用消耗
》》測試方法
選取使用者函數、類方法、靜態方法、內建函數各一種,函數本身不做任何事情,直接返回,主要測試空函數調用的消耗。測試結果為每秒可執行次數 測試中為去除其他影響,所有函數名字長度相同
》》測試結果如

》》結果分析
通過測試結果可以看到,對於使用者自己編寫的php函數,不管是哪種類型,其效率是差不多的,均在280w/s左右。如我們預期,即使是空調,內建函數其效率也要高很多,達到780w/s,是前者是3倍。可見,內建函數調用的開銷還是遠低於使用者函數。從前面原理分析可知主要差距在於使用者函數調用時初始化符號表、接收參數等操作。

內建函數和使用者函數效能對比

》》測試方法
內建函數和使用者函數的效能對比,這裡我們選取幾個常用的函數,然後用php實現相同功能的函數進行一下效能對比。測試中,我們選取字串、數學、數組中各一個典型進行對比,這幾個函數分別是字串截取(substr)、10進位轉2進位(decbin)、求最小值(min)和返回數組中的所以 key(array_keys)。
》》測試結果如

》》結果分析
從測試結果可以看出,如我們預期,內建函數在總體效能上遠高於普通使用者函數。尤其對於涉及到字串類操作的函數,差距達到了1個數量級。因此,函數使用的一個原則就是如果某功能有相應的內建函數,盡量使用它而不是自己編寫php函數。對於一些涉及到大量字串操作的功能,為提高效能,可以考慮用擴充來實現。比如常見的富文本過濾等。
和C函數效能對比

》》測試方法
我們選取字串操作和算術運算各3種函數進行比對,php用擴充實現。三種函數是簡單的一次演算法運算、字串比較和多次的演算法運算。除了本身的兩類函數外,還會測試將函數空調開銷去掉後的效能,一方面比對一下兩種函數(c和php內建)本身的效能差異,另外就是側面印證空調函數的消耗 測試點為執行10w次操作的時間消耗
》》測試結果如

》》結果分析
內建函數和C函數的開銷在去掉php函數空調用的影響後差距較小,隨著函數功能越來越複雜,雙方效能趨近於相同。這個從之前的函數實現分析中也容易得到論證,畢竟內建函數就是C實現的。函數功能越複雜,c和php的效能差距越小 相對c來說,php函數調用的開銷大很多,對於簡單函數來說效能還是有一定影響。因此php中函數不宜嵌套封裝太深。
偽函數及其效能

在php中,有這樣一些函數,它們在使用上是標準的函數用法,但底層實現卻和真正函數調用完全不同,這些函數不屬於前文提到的三種function中的任何一類,其實質是一條單獨的opcode,這裡估且叫做偽函數或者指令函數。

如上所說,偽函數使用起來和標準的函數並無二致,看起來具有相同的特徵。但是他們最終執行的時候是被zend反映成了一條對應的指令(opcode)來調用,因此其實現更接近於if、 for、算術運算等操作。
》》php中的偽函數
isset
empty
unset
eval
通過上面的介紹可以看出,偽函數由於被直接翻譯成指令來執行,和普通函數相比少了一次函數調用所帶來的開銷,因此效能會更好一些。我們通過如下測試來做一個對比。 Array_key_exists和isset兩者都可以判斷數組中某個key是否存在,看一下他們的效能

從圖上可以看出,和 array_key_exists相比,isset效能要高出很多,基本是前者的4倍左右,而即使是和空函數調用相比,其效能也要高出1倍左右。由此也側面印證再次說明了php函數調用的開銷還是比較大的。

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.