本測試資料真實,但隻做為參考。歡迎大家讨論。
除做比較外,也可供php,jsp程式員參考,以便優化自己的程式。
本測試由一直漂(ipaddr,bcomcn)原創,歡迎轉載,并注明出處。問題回報:admin.net(at)163.com
測試環境:
硬體:p4 2.4g,1g記憶體
軟體:windowsxp+apache2.0.54+php4.4.0+mysql4.1.14+tomcat5.0.28
讨論位址:
循環n次,并做整型自加運算。
測試代碼:
測試類型
jsp int整型
jsp long整型
jsp long整型2
php
php2
測試代碼
int i=0;
while (i<xxxx)
{
i++;
}
long l=0;
while (l<xxxx)
l++;
l=l+1;
$i=0;
while ($i<xxxx)
$i++;
$i=$i+1;
測試結果(機關:毫秒)
測試結果說明:m-n表示主要波動範圍介于m和n之間;n表示出現次數非常之多的數值或平均值,m(x,y)表示偶爾會出現x,y。以下相同。
xxxx取值
jsplong整型
jsplong整型2
1000
0-1
10000
3-4
6-7
100000
0(16,32)
34-35
51-52
1000000
0(10)
348-368
527-534
10000000
0(13)
16-32
32-78
3547-3585
5239-5390
100000000
0(16)
266-281
265-281
35309-35486
1000000000
0(16,743)
2625-2676
2203-3687
java的算術運算,優化得很好,估計是直接的對應cpu的指令,數值再大,算術運算性能都很平穩。
需要注意的是,long的運算時間要比int的運算時間要長一些(畢竟是32位的系統),是以,在無需用到long時,盡量不要用long,而用int.
php是弱類型的變量,算術運算很不盡人意,估計不是直接對應機器碼的算術運算。
php算術運算的過程猜測如下,在運算前需要檢測變量是否是數值,并要将非數值轉換成數值,比如,php可以做這樣的運算:100+"zhoutang",結果等于100.正是因為是弱類型語言,加上運算前的檢測和轉換,是以才導緻算術運算的性能低下。
php的單次運算時間比較穩定,大概每10000次算術加運算花費的時間約為3.5ms
不同的運算方法,也對性能有影響。
字元串連接配接運算對比。
jsp
string str="";
while (str.length()< xxxx)
str+="a";
$str="";
while (strlen($str)< xxxx)
$str.="a";
0-16
1
656-703
9-10
105078-105235
95-103
java的字元串是用對象處理,很明顯,在字元串的比較過程中,java比php差很遠。(因為字元串操作,很大部分要做連接配接,這裡隻比較連接配接運算,另外粗略比較了一下substring,兩者的差别不是很大)
php的字元串運算,估計很多是直接調用c的字元串函數,是以效率會高很多。
在做web開發中,字元串的連接配接操作還是很頻繁的(包括很多時候生成sql字元串),是以,在算術運算和字元串運算兩個方面,java(jsp)優勢不明顯,與php各有所長。
循環n次做資料庫打開,查詢,關閉操作。主要對jsp直接連資料庫,jsp連接配接池連資料訓,php直接連資料庫,php持久連資料庫做比較。
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;
while (i<xxx)
con=drivermanager.getconnection(dburl,dbuser,dbpwd);
stmt=con.createstatement();
stmt.executeupdate(strsql);
stmt.close();
con.close();
stmt=null;
con=null;
jsp連接配接池
context ctx=new initialcontext();
datasource
ds=(datasource)ctx.lookup("java:comp/env/jdbc/mysql");
string strsql="update tbluser set userlc=userlc+1 where
con=ds.getconnection();
$dbhost="localhost";
$dbuser="root";
$dbpwd="";
$dbname="zhoutang";
$strsql="update tbluser set
userlc=userlc+1 where userid=100";
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);
php持久連接配接
$strsql="update tbluser set userlc=userlc+1 where
mysql_pconnect($dbhost, $dbuser, $dbpwd)
or die(‘could not connect:
‘ . mysql_error());
50
437-600
31-50
219-232
34-37
100
890-1047
62-94
448-468
69-73
200
2141-2263
157-189
948-979
159-175
500
5078-5140
375
2118-2221
358-379
普通連接配接,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大很多。(這裡特意将打開資料庫操作放在循環體做比較)
在web開發過程上,檔案操作一般不可缺少,大多數web系統都會上傳或對檔案操作。
綜合測試各種檔案操作,測試的過程是首先判斷某檔案是否存在,存在的話删除檔案,再建立檔案,再往檔案裡寫一定長度的内容。整個過程循環n次。
string filename="jsp.txt";
string
filepath=request.getrealpath("");
int
j=0;
file f=new
file(filepath,filename);
if(f.exists())
f.delete();
f.createnewfile();
filewriter fw=new filewriter(filepath+file.separator+filename);
while (j<2*i)
fw.write(j+"\r\n");
j++;
fw.close();
$filename="./php.txt";
while
($i<xxxx)
if (file_exists($filename))
unlink($filename);
$handle=fopen($filename,"x");
$j=0;
($j<2*$i)
fwrite($handle,$j."\r\n");
$j++;
fclose($handle);
265-292(326,431)
346-367
1703-2065
3256-3474
4062-4398
9316-9348
這個測試結果有點意外,本以為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秒)。
以上資料隻能做為參考,同樣的程式,在其它配置的系統,我也做了簡單的測試:
(安裝東西比較多,比較亂,運作一年多沒重裝,由于是工作機,是以作業系統對應用程式優化,而不是對後端服務優化;所測得的資料,比xp下測得的資料要大很多,比如php連接配接mysql循環500次,大約需要16000ms。),粗略的測試的結果是:
算術運算和字元串運算:算術運算,jsp領先很多,字元串運算,php領先很多,和測試機的結果一緻。
連接配接資料庫:php與jsp連mysql速度差距不大,php大概快20%左右,奇怪的是我用pconnect連與connect是一樣的結果,未測試jsp的連接配接池。估計jsp用連接配接池會快很多。
檔案操作:php的檔案操作比jsp性能高出約30%!與測試機的結果有點相差比較大,php領先。
算術運算和字元串運算:和其它環境測試結果一緻,jsp在算術運算時領先,php在字元串運算時領先很多很多。
連接配接資料庫:執行500次循環,php用connect連接配接,花費185ms,php使用pconnect連接配接,花費70ms;jsp未用連接配接池,花費2030ms。
檔案操作:jsp領先很多,1000次循環,jsp花費1500ms左右,php花費7000ms左右。
不管什麼平台系統,測試結果表明,jsp和php在做web開發時,性能差距不大,隻能說各有所長,jsp在資料庫操作以及字元串操作方面不如php,而php在檔案操作及算術運算是,不及jsp。
此外,同種語言,在不同的平台表現也不一樣,根據我的測試結果表明,linux下php,jsp的性能都要優于windows的。
語言
如何擷取運作時間
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>");
$timestart=0;
$timeend=0;
$timestart=mictime();
$timeend=mictime();
echo
"開始時間:".$timestart."毫秒<br>";
"結束時間:".$timeend."毫秒<br>";
"花費時間:".($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.techempower.com/benchmarks/