天天看点

JSP,PHP详细性能测试一.算术运算二.字符串运算三.数据库查询四.文件操作五.总结六.其它环境简单测试七.运行时间的获取

本测试数据真实,但只做为参考。欢迎大家讨论。

除做比较外,也可供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/