PHP與JSP上演超詳細性能測試大PK
在網上有多關于PHP與JSP的性能比較,有些結果表明PHP比JSP性能低了很多,本文將客觀的展現PHP與JSP的性能測試比較,且都為真實數據。當然, 這里面并沒有包含.Net。
測試環境:
◆硬件:P4 2.4G,1G內存
◆軟件:WindowsXP+Apache2.0.54+PHP4.4.0+Mysql4.1.14+Tomcat5.0.28
一.算術運算
a.測試標準
循環N次,并做整型自加運算。
b.測試代碼
測試結果(單位:毫秒)
測試結果說明:m-n表示主要波動范圍介于m和n之間;n表示出現次數非常之多的數值或平均值,m(x,y)表示偶爾會出現x,y。以下相同。
c.結論
Java的算術運算,優化得很好,估計是直接的對應CPU的指令,數值再大,算術運算性能都很平穩。需要注意的是,long的運算時間要比int的運算時間要長一些(畢竟是32位的系統),所以,在無需用到long時,盡量不要用long,而用int.
PHP是弱類型的變量,算術運算很不盡人意,估計不是直接對應機器碼的算術運算。PHP算術運算的過程猜測如下,在運算前需要檢測變量是否是數值,并要將非數值轉換成數值,比如,PHP可以做這樣的運算:100+"zhoutang",結果等于100.正是因為是弱類型語言,加上運算前的檢測和轉換,所以才導致算術運算的性能低下。PHP的單次運算時間比較穩定,大概每10000次算術加運算花費的時間約為3.5ms
不同的運算方法,也對性能有影響。
二.字符串運算
a.測試標準
字符串連接運算對比。
b.測試
測試結果(單位:毫秒)
c.結論
Java的字符串是用對象處理,很明顯,在字符串的比較過程中,Java比PHP差很遠。(因為字符串操作,很大部分要做連接,這里只比較連接運算,另外粗略比較了一下substring,兩者的差別不是很大)
PHP的字符串運算,估計很多是直接調用C的字符串函數,所以效率會高很多。在做Web開發中,字符串的連接操作還是很頻繁的(包括很多時候生成SQL字符串),所以,在算術運算和字符串運算兩個方面,Java(JSP)優勢不明顯,與PHP各有所長。
#p#
三.數據庫查詢
a.測試標準
循環N次做數據庫打開,查詢,關閉操作。主要對JSP直接連數據庫,JSP連接池連數據訓,PHP直接連數據庫,PHP持久連數據庫做比較。
b.測試代碼
- JSP
- String dbUrl, dbUser, dbPwd, strSQL;
- dbUrl = "jdbc:mysql://localhost:3306/zhoutang";
- dbUser = "root";
- dbPwd = "";
- strSQL = "update tblUser set UserLC=UserLC+1 where UserID=100";
- Class.forName("com.mysql.jdbc.Driver");
- Connection con;
- Statement stmt;
- int i = 0;
- while (i < XXX) {
- con = DriverManager.getConnection(dbUrl,dbUser,dbPwd);
- stmt = con.createStatement();
- stmt.executeUpdate(strSQL);
- stmt.close();
- con.close();
- stmt = null;
- con = null;
- i++;
- }
- JSP連接池
- Context ctx = new InitialContext();
- DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/mysql");
- String strSQL = "update tblUser set UserLC=UserLC+1 where UserID=100";
- Connection con;
- Statement stmt;
- int i = 0;
- while (i < XXXX) {
- con = ds.getConnection();
- stmt = con.createStatement();
- stmt.executeUpdate(strSQL);
- stmt.close();
- con.close();
- stmt = null;
- con = null;
- i++;
- }
- PHP
- $dbHost = "localhost";
- $dbUser = "root";
- $dbPwd = "";
- $dbName = "zhoutang";
- $strSQL = "update tblUser set UserLC=UserLC+1 where UserID=100";
- $i = 0;
- while ($i < XXXX) {
- $link = mysql_connect($dbHost, $dbUser, $dbPwd) or die('Could not connect: ' . mysql_error());
- mysql_select_db($dbName);
- mysql_query($strSQL);
- mysql_close($link);
- $i++;
- }
- PHP持久連接
- $dbHost = "localhost";
- $dbUser = "root";
- $dbPwd = "";
- $dbName = "zhoutang";
- $strSQL = "update tblUser set UserLC=UserLC+1 where UserID=100";
- $i=0;
- while ($i< XXXX) {
- $link = mysql_pconnect($dbHost, $dbUser, $dbPwd) or die('Could not connect: ' . mysql_error());
- mysql_select_db($dbName);
- mysql_query($strSQL);
- mysql_close($link);
- $i++;
- }
測試結果(單位:毫秒)
c.結論
普通連接,Java連Mysql的速度是要比PHP慢的一倍左右。Java使用連接池技術,性能提升非常明顯。
PHP使用的持久連接(pconnect)性能即然相當于Java的連接池,結果實在讓人不可思議,本來挺擔心PHP連數據庫的,因為沒連接池可用,特意在網上找了一些資料,沒發現PHP可用的連接池,相關提法都很少,很多PHP程序員甚至沒聽過這概念,這樣的結果,確實讓我也大吃一驚。不過,話說回來,pconnect的原理,和連接池差不多的,都是程序關閉連接,但PHP并不真正關閉,再次打開時,直接使用可用的連接。但是,PHP的實現確實比Java方便多了,只需加個字母,就輕易實現,Java則麻煩一些,我配置Tomcat的連接池都費了些時間,按官方文檔,在tomcat5.0.28下沒配置成功,在CSDN上面,也看到很多新手發出求救,很多配置不成功的,***自己摸索出來了,配置方法可參考我的Blog。
如果將連接數據庫和關閉數據庫的操作,移到循環外面,剛PHP和JSP的執行時間都差不多,循環50次約16ms。可見,數據庫操作中,打開連接是相當耗資源的,其它操作,與語言差別不大。JSP在連接數據庫的時候,開銷比PHP大很多。(這里特意將打開數據庫操作放在循環體做比較)
#p#
四.文件操作
在Web開發過程上,文件操作一般不可缺少,大多數Web系統都會上傳或對文件操作。
a.測試標準
綜合測試各種文件操作,測試的過程是首先判斷某文件是否存在,存在的話刪除文件,再新建文件,再往文件里寫一定長度的內容。整個過程循環N次。
b.測試結果
- JSP測試代碼:
- String fileName = "jsp.txt";
- String filePath = request.getRealPath("");
- int i = 0;
- int j = 0;
- while (i < XXXX) {
- File f = new File(filePath,fileName);
- if (f.exists()) {
- f.delete();
- }
- f.createNewFile();
- FileWriter fw = new FileWriter(filePath + File.separator + fileName);
- j = 0;
- while (j < 2 * i) {
- fw.write(j + "\r\n");
- j++;
- }
- fw.close();
- i++;
- }
- PHP測試代碼:
- $fileName = "./php.txt";
- $i = 0;
- while ($i < XXXX) {
- if (file_exists($fileName)) {
- unlink($fileName);
- }
- $handle = fopen($fileName, "x");
- $j = 0;
- while ($j < 2 * $i) {
- fwrite($handle,$j."\r\n");
- $j++;
- }
- fclose($handle);
- $i++;
- }
測試結果(單位:毫秒)
c.結論
這個測試結果有點意外,本以為PHP會大勝的項目,卻讓JSP***,循環次數大的時候,PHP比JSP慢一倍。有點不可思議。
五.總結
總體來說,PHP與JSP在性能上,差別不了很遠,各有優勢。JSP雖是編譯執行,但卻要通過JVM,性能會有所下降。從功能上說,JSP的相對強大一些,主要是因為有Java的支撐,在一些很大型的企業中,用JSP有優勢(主要是有Java支撐),但一般的企業或一般的應用,PHP完全可以應付。另外,PHP比JSP更容易上手。另外,個人說為,做同樣的WEB系統,PHP相對JSP來說,復雜度可能會低一些(JSP所有的技術都用上的話,估計架構環境,系統設計都夠麻煩的,而且,Java體系各種技術和產品比較開放和松散,文檔相對來說有點雜亂,至少我認為Tomcat的文檔做得沒有Apache,PHP的好。)。
PHP小巧而靈活,JSP就顯得寵大,而且,概念眾多,個人認為Java體系有故意夸大技術復雜度的嫌疑。
此外,PHP還有Zend可用,本來想裝上Zend再來測試一番的,這幾天Zend的網站老是上不去。據有關測試表明,Zend能提升PHP的性能大約100%左右。也有說30-40%的,也有說600%的。估計是算術運算能提升個檔次,其它操作,最多提升30-40%左右。
在整個測試過程中,每個取值我都會測多次,一般10s以下的運算,我至少測10次,10s以上的運算,至少測3次。PHP的測試結果都比較穩定,每次測出的結果差別不是很大,從統計學的角度來說,方差比較小。JSP相對來說,偶爾會出現一些值,偏離平均值比較遠,而且,由于需要編譯的原因,***執行一般時間比較長(雖然從程序里顯示的數值看不出***執行的時間差距,但在程序開始執行前,編譯需要點時間。編譯后才開始執行,所以程序顯示的結果看不出來。),所以,JSP的測試,沒取***運行的結果。
另外,在測試連接數據庫的過程中,由于一時疏忽,忘了在循環體內i++,導致出現死循環。所以,也特意做了幾個死循環測試。算術運算測試,JSP死循環時,瀏覽器點了停止按鈕,tomcat仍繼續執行,CPU一直是100%,只有在任務管理器里停了tomcat,才得以停止死循環;PHP算術運算死循環,由于php.ini里有設置程序執行的最長時間和***內存,所以,死循環能夠自動結束。數據庫連接死循環,JSP在循環大概900多次后,出現異常,報錯,提示無法連接;PHP循環1500次后,仍然沒有結束,只好在任務管理器里結束apache進程(我的php.ini設置PHP最長執行時間為300秒)。
六.其它環境簡單測試
以上數據只能做為參考,同樣的程序,在其它配置的系統,我也做了簡單的測試:
I.p4 2.4G,512M DDR,Windows server2000的工作機
(安裝東西比較多,比較亂,運行一年多沒重裝,由于是工作機,所以操作系統對應用程序優化,而不是對后端服務優化;所測得的數據,比XP下測得的數據要大很多,比如PHP連接Mysql循環500次,大約需要16000ms。),粗略的測試的結果是:
算術運算和字符串運算:算術運算,JSP領先很多,字符串運算,PHP領先很多,和測試機的結果一致。
連接數據庫:PHP與JSP連Mysql速度差距不大,PHP大概快20%左右,奇怪的是我用pconnect連與connect是一樣的結果,未測試JSP的連接池。估計JSP用連接池會快很多。
文件操作:PHP的文件操作比JSP性能高出約30%!與測試機的結果有點相差比較大,PHP領先。
II.p4 2.66G,1G DDR,Linux服務器
算術運算和字符串運算:和其它環境測試結果一致,JSP在算術運算時領先,PHP在字符串運算時領先很多很多。
連接數據庫:執行500次循環,PHP用connect連接,花費185ms,PHP使用pconnect連接,花費70ms;JSP未用連接池,花費2030ms。
文件操作:JSP領先很多,1000次循環,JSP花費1500ms左右,PHP花費7000ms左右。
III.總結
不管什么平臺系統,測試結果表明,JSP和PHP在做Web開發時,性能差距不大,只能說各有所長,JSP在數據庫操作以及字符串操作方面不如PHP,而PHP在文件操作及算術運算是,不及JSP。
此外,同種語言,在不同的平臺表現也不一樣,根據我的測試結果表明,Linux下PHP,JSP的性能都要優于Windows的。
七.運行時間的獲取
- JSP
- long timeStart = 0;
- long timeEnd = 0;
- timeStart = Calendar.getInstance().getTimeInMillis();
- //中間代碼
- timeEnd = Calendar.getInstance().getTimeInMillis();
- out.println("開始時間:" + timeStart + "毫秒<br>");
- out.println("結束時間:" + timeEnd + "毫秒<br>");
- out.println("花費時間:" + (timeEnd - timeStart) + "毫秒<br>");
- PHP
- $timeStart = 0;
- $timeEnd = 0;
- $timeStart = mictime();
- //中間代碼
- $timeEnd = mictime();
- echo "開始時間:".$timeStart."毫秒<br>";
- echo "結束時間:".$timeEnd."毫秒<br>";
- echo "花費時間:".($timeEnd - $timeStart)."毫秒<br>";
- function mictime() {
- //由于PHP支持不支持long型,所以,只取了5位秒數,再加上毫秒。時間段比較,前面的可以忽略
- list($usec, $sec) = explode(" ", microtime());
- $sec = substr($sec, -5);
- $usec = ceil($usec * 1000);
- while (strlen($usec) < 3) {
- $usec="0".$usec;
- }
- return $sec.$usec;
- }
原文鏈接:http://www.360doc.com/content/10/0514/20/2807_27615633.shtml
【編輯推薦】