這篇文章跟大家介紹一分鐘解讀PHP是解釋型還是編譯型的?有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。
編譯型語言
#解釋型語言
OK,透過上面概念的簡單了解,你可能對解釋型、編譯型語言有了一個大概的了解。既然兩者平分天下,下面我們就來看看兩者各有什麼優勢吧。
編譯型語言
劣勢
可執行的編譯型程式碼比相同的解釋型程式碼大很多。例如,C/C 的.exe檔要比同樣功能的Java的.class檔大很多。
編譯型程式是面向特定平台的因而是平台依賴的。
解釋器比編譯器容易實作
######極佳的平台獨立性############高度的安全性-這是網路應用迫切需要的############ 中間語言程式碼的大小比編譯型執行程式碼小得多############。 ######OK,透過上面的學習,相信大家對解釋型語言與編譯型語言有了大致的了解,而且PHP語言是解釋型語言,而且解釋PHP語言的解釋器就是Zend引擎。
而且,根據兩者的優劣勢比較可以發現,編譯型語言更適合做底層的操作,而解釋型語言較多的用在了Web開發上。
再深入探討下PHP的執行過程:
php的編譯和執行是分開的,也就是:先執行完編譯,而後再執行。很多人會說:c 也是如此啊,確實如此。不過php的這種分離可以提供我們很多便利,當然不可避免也有很缺點。
先說整個過程:
①php會呼叫編譯函數zend_compile_file()來進行編譯。這個函數的具體實現其實是包含兩個主要過程的:詞法分析(Lex實現),語法分析(Yacc實現)。執行完這個函數之後:php腳本的編譯就算結束了。這個函數的輸入是:php腳本文件,而輸出則是op_array.簡單一點說:編譯過程就是把腳本給解析成一條條php虛擬機可以處理的指令,而op_array就是這些指令做成的一個array而已(這很類似一些編譯型語言編譯產生的組譯程式碼了,也是一條條的命令)。
②:之後php虛擬機會呼叫zend_execute()這個函數來執行。這個函數的輸入就是上邊編譯階段產生的op_array,在這裡他會解析每個指令並處理。由於op指令一共有150左右,所以它需要處理這150中指令。這裡會產生一個很有趣的問題:它是如何處理這150種指令的呢?首先每條指令都是有對應的處理器來處理的。所以:虛擬機會依據op_array中各條指令的類型來分發給回應的處理器來處理。
這裡有兩個小問題: 1:這裡的處理器是什麼? 2:如何分發的?
要解決這兩個問題都是從分發機制上來解釋:php虛擬機分發指令的機制有三種:CALL, SWITCH, 和GOTO這三種類型.php預設是使用CALL方式, 也就是所有的opcode處理器都定義為函數, 然後供虛擬機調用. 這種方式是傳統的方式, 也一般被認為是最穩定的方式.而SWITCH方式和GOTO方式則是通過switch和goto來分發opcode到對應的處理邏輯(段)執行的.
現在來回答上邊兩個問題:
1:處理器其實是處理op指令的邏輯。其可以以函數的形式存在,也可能是以邏輯段的方式存在,這取決於命令的分發方式。
2:分發方式有三種call,switch和goto。哪種效率高呢?其實從上邊解釋已經可以初步了解了。 switch和goto都是在zend_execute()這個函數中有對應的邏輯段,直接執行就可以了。而call是在zend_execute()這個函數中執行函數呼叫。明擺著:函數呼叫效率是最低的,呼叫一次就得壓棧啊!所以效率上:call是最低的。對於switch和goto:例如要執行第三種指令的處理:switch還要先挨個判斷是不是前兩種,而goto根本不需要判斷,直接跳到第三種指令的邏輯程式碼段去執行,這比switch少了順序從上到下判斷的損耗,所以:goto效率又比switch要高。所以這三種分發方式大致而言:goto > switch > call
再說一次php這種編譯和執行分離的弱點:
其實也不能算是弱點,雖然zend engine(php的虛擬機器)將編譯和執行嚴格分開,但是對於使用者而言:就跟沒分開一樣,因為我每次執行一個php腳本請求都是要執行:編譯->執行這兩個階段。任何一個階段都少不了。那麼這一點我們可以拿來和c 這種編譯型語言做一下比較: 同一個請求運行100遍
①對於c ,由於其前期只要編譯一遍,編譯好就不會再重複編譯了,只需要執行就ok,所以其損耗為:
1次編譯100次執行
②對於php,其每次都會編譯執行,因此其損耗為:
100次編譯100次執行
顯然:解釋性語言從數量來看:其消耗量是比編譯型語言多的多。說穿了就是:php這種編譯和執行相分離並不是真正的分離。而c 那種才算是真正的分離。
php也早就意識到這個問題了,於是就想了一個辦法來解決這個問題:這個解決方案就是eAccelerator。主要想法如下:
當腳本第一次運行後,以某種方式保存編譯後腳本(裡邊存放的是op_array),在我們規定的緩存有效時間內,當第二次運行該腳本時就不在進行重複性的編譯工作,而是直接呼叫執行前面儲存的編譯後文件,大大提高了程式效能。
最後說一下php編譯和執行分離的優點;
這個優點其實是針對程式設計師而言,對使用者而言沒什麼。因為這兩個階段的分離,我們可以在這裡做一些我們想做的事情。
例如想做檔案加解密,你想把一些php腳本原始碼檔案加密,讓使用者看不到原始碼。同時呢這個加密後的源碼檔案又可以被php虛擬機器所解析和處理。當然:要實現這個前提是你先想好加解密演算法並保證這個是可逆的過程。
現在你對php原始碼檔案已經加密了,此時你需要定義一下這種加密檔案的後綴,假設為:*.buaa。那問題就是:我們要怎麼讓php虛擬機器可以處理這種字尾的檔案呢?這就要用到上邊所說的編譯和執行相分離的過程了。
回想:編譯階段的輸入是php來源文件,輸出是op_array。 ok,我們就在這個階段做文章。主要想法為:首先在zend_compile_file()這個編譯函數中:看一下輸入檔的字尾:如果是正常的.php那就走正常邏輯,如果是*.buaa,那就先解密然後再走正常邏輯。 。 。
結論:
PHP是解釋型語言,將PHP程式碼解釋為opcode之後再交由Zend引擎執行。
使用APC快取了opcode,減少了PHP解釋為opcode這一步的時間。
推薦學習:php影片教學
以上是一分鐘解讀PHP是解釋型還是編譯型的?的詳細內容。更多資訊請關注PHP中文網其他相關文章!