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

2021-07-15 10:00:55 字數 3142 閱讀 8943

類方法

類方法其執行原理和使用者函式是相同的,也是翻譯成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函式呼叫的開銷還是比較大的。

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

前言 在任何語言中,函式都是最基本的組成單元。對於php的函式,它具有哪些特點?函式呼叫是怎麼實現的?php函式的效能如何,有什麼使用建議?本文將從原理出發進行分析結合實際的效能測試嘗試對這些問題進行回答,在了解實現的同時更好的編寫php程式。同時也會對一些常見的php函式進行介紹。php函式的分類...

百度2013研發工程師A筆試

1 動態鏈結庫和靜態鏈結庫的優缺點 動態鏈結的優點 1 不占用源程式 段,節省空間。2 使程式更容易更新。3 減少物理頁面的切入。4 增加程式的可擴充套件性 動態鏈結的缺點 1 效能損失 2 相容性問題 靜態鏈結的優點 1 裝載速度快。2 不存在版本相容的問題 靜態鏈結的缺點 1 體積問題 2 可擴...

筆試收錄 百度 軟體工程師

1 請實現兩棵樹是否相等的比較,相等返回,否則返回其他值,並說明演算法複雜度。資料結構為 typedef struct treenodetreenode 函式介面為 int comptree treenode tree1,treenode tree2 注 a b兩棵樹相等當且僅當root c roo...