從原理分析PHP的性能,主要從以下幾個(gè)方面:內(nèi)存管理、變量、函數(shù)、運(yùn)行機(jī)制、網(wǎng)絡(luò)模型來(lái)進(jìn)行分析。
1.內(nèi)存管理
類似Nginx的內(nèi)存管理方式,PHP在內(nèi)部也是基于內(nèi)存池,并且引入內(nèi)存池的生命周期概念。在內(nèi)存池方面,PHP對(duì)PHP腳本和擴(kuò)展的所有內(nèi)存相關(guān)操作都進(jìn)行了托管。對(duì)大內(nèi)存和小內(nèi)存的管理采用了不同的實(shí)現(xiàn)方式和優(yōu)化。在內(nèi)存分配和回收的生命周期內(nèi),PHP采用一次初始化申請(qǐng)+動(dòng)態(tài)擴(kuò)容+內(nèi)存標(biāo)識(shí)回收機(jī)制,并且在每次請(qǐng)求結(jié)束后直接對(duì)內(nèi)存池進(jìn)行重新mask。
2.變量
總所周知,PHP是一種弱變量類型的語(yǔ)言,所以在PHP內(nèi)部,所有的PHP變量都對(duì)應(yīng)成一種類型Zval,其中具體定義如下:
在變量方面,PHP做了大量的優(yōu)化工作,比如說(shuō)Reference counting和copy on writer機(jī)制。這樣能夠保證內(nèi)存使用上的優(yōu)化,并且減少內(nèi)存拷貝次數(shù)(請(qǐng)參考http://blog.xiuwz.com/2011/11...)。在數(shù)組方面,PHP內(nèi)部采用高效的hashtable來(lái)實(shí)現(xiàn)。
3.函數(shù)
在PHP內(nèi)部,所有的PHP函數(shù)都回轉(zhuǎn)化成內(nèi)部的一個(gè)函數(shù)指針。比如說(shuō)擴(kuò)展中函數(shù)
ZEND_FUNCTION ( my_function );//類似function my_function(){}
在內(nèi)部展開后就會(huì)是一個(gè)函數(shù)
void zif_my_function ( INTERNAL_FUNCTION_PARAMETERS );
void zif_my_function(
int ht,
zval * return_value,
zval * this_ptr,
int return_value_used,
zend_executor_globals * executor_globals
);
從這個(gè)角度來(lái)看,PHP函數(shù)在內(nèi)部也是對(duì)應(yīng)一個(gè)函數(shù)指針。
4.運(yùn)行機(jī)制
在話說(shuō)PHP性能的時(shí)候,很多人都會(huì)說(shuō)“C/C++是編譯型,JAVA是半編譯型,PHP是解釋型”。也就是說(shuō)PHP是先動(dòng)態(tài)解析再代碼運(yùn)行的,所以從這個(gè)角度來(lái)看,PHP性能必然很差。
的確,從PHP腳本運(yùn)行來(lái)輸出,的確是一個(gè)動(dòng)態(tài)解析再代碼運(yùn)行的過(guò)程。
PHP的運(yùn)行階段也分成三個(gè)階段:
●Parse。語(yǔ)法分析階段。
● Compile。編譯產(chǎn)出opcode中間碼。
● Execute。運(yùn)行,動(dòng)態(tài)運(yùn)行進(jìn)行輸出。
5.動(dòng)態(tài)運(yùn)行
從上面的幾個(gè)分析來(lái)看,PHP在內(nèi)存管理、變量、函數(shù)、運(yùn)行機(jī)制等幾個(gè)方面都做了大量的工作,所以從原理來(lái)看,PHP不應(yīng)該存在性能問(wèn)題,性能至少也應(yīng)該和JAVA比較接近。
但為什么還有很多人感覺PHP慢呢?尤其是一些計(jì)算量的性能對(duì)比上,總發(fā)現(xiàn)PHP處理的性能相對(duì)比較低效。這個(gè)時(shí)候就不得不談PHP動(dòng)態(tài)語(yǔ)言的特性所帶來(lái)的性能問(wèn)題了,由于PHP是動(dòng)態(tài)運(yùn)行時(shí),所以所有的變量、函數(shù)、對(duì)象調(diào)用、作用域?qū)崿F(xiàn)等等都是在執(zhí)行階段中才確定的。這個(gè)從根本上決定了PHP性能中很難改變的一些東西:在C/C++等能夠在靜態(tài)編譯階段確定的變量、函數(shù),在PHP中需要在動(dòng)態(tài)運(yùn)行中確定,也就決定了PHP中間碼不能直接運(yùn)行而需要運(yùn)行在Zend Engine上。
6.網(wǎng)絡(luò)模型
目前采用PHP的方式,比較理想和通用的模式是采用fastcgi(PHP-FPM)。Php-fpm在網(wǎng)絡(luò)模型上比較類似nginx,采用了多進(jìn)程Master+多worker的模式。Php-fpm本身是基于libevent中的epoll模型。從網(wǎng)絡(luò)模型來(lái)看,該方式也不會(huì)和其他網(wǎng)絡(luò)模型存在性能差異。
7.結(jié)論
從上面分析來(lái)看,在基礎(chǔ)的內(nèi)存管理、變量、函數(shù)、運(yùn)行機(jī)制、網(wǎng)絡(luò)模型方面,PHP本身并不會(huì)存在明顯的性能差異,但由于PHP的動(dòng)態(tài)運(yùn)行特性,決定了PHP和其他的編譯型語(yǔ)言相比,所有的變量查找、函數(shù)運(yùn)行等等都會(huì)多一些hash查找的CPU開銷和額外的內(nèi)存開銷,至于這種開銷具體有多大,可以通過(guò)后續(xù)的基準(zhǔn)性能和對(duì)比分析得出。
因此,也可以大體看出PHP不太適合的一些場(chǎng)景:大量計(jì)算性任務(wù)、大數(shù)據(jù)量的運(yùn)算、內(nèi)存要求很嚴(yán)格的應(yīng)用場(chǎng)景。如果要實(shí)現(xiàn)這些功能,也建議通過(guò)擴(kuò)展的方式實(shí)現(xiàn),然后再提供鉤子函數(shù)給PHP調(diào)用。這樣可以減低內(nèi)部計(jì)算的變量、函數(shù)等系列開銷。
點(diǎn)關(guān)注,不迷路
好了各位,以上就是這篇文章的全部?jī)?nèi)容了,能看到這里的人呀,都是人才。之前說(shuō)過(guò),PHP方面的技術(shù)點(diǎn)很多,也是因?yàn)樘嗔?,?shí)在是寫不過(guò)來(lái),寫過(guò)來(lái)了大家也不會(huì)看的太多,所以我這里把它整理成了PDF和文檔,如果有需要的可以點(diǎn)這里https://shimo.im/docs/rjJttdvCJpYtHpW3/ 《進(jìn)階PHP月薪30k>>>架構(gòu)師成長(zhǎng)路線【視頻、面試文檔免費(fèi)獲取】》

