http://www.prahladyeri.com/2014/06/php-vs-node-js-real-statistics/
在网络编程领域,常用的解决方案就是JSP(SSH)、ASP.NET、PHP加上LAMP这种架构。不过,现在这个大家庭加入了NodeJS,这个轻量级的基于JavaScript服务端库的平台可以使用异步I/O的方式来提升整体的性能。
I/O操作是网络传输中占用资源最大的模块。当Apache服务器接收到请求时,它会将它传输到PHP解释器来执行任何动态脚本的模块。这也是最棘手的模块,如果PHP脚本需要从磁盘或者数据库中读写数据,这回成为整个环节中最慢的一环。如果调用PHP中的file_get_contents()函数,整个线程都会被阻塞直到文件内容被获取到。在此期间服务器不能进行任何操作。如果大量用户同时发出此类请求,那么这些请求都会进入一个等待队列,因为所有的线程都被阻塞了。
而非阻塞操作也是NodeJs最大的特点之一。鉴于NodeJs在它所有的函数中都进行了异步操作,上述场景中的情况在NodeJs中反应就大相径庭。一旦文件调用了fs.readFile函数,该线程会被立刻释放。而当I/O操作结束之后,会自动回调某个在readFile中指定的函数对传入的数据参数进行操作。同时,该线程可以用于处理其他请求。
虽然从原理上可以看出这种机制能够有效地降低用户等待时间,但是还是需要用数据来说明一切。
1.接受请求。
2. 随机生成108千字节的字符串。
3. 将字符串写入到磁盘文件中。
4. 从磁盘文件中读取内容。
5. 将字符串输出到响应流中。
PHP代码 index.php:
<?php //index.php $s=""; //generate a random string of 108KB and a random filename $fname = chr(rand(0,57)+65).chr(rand(0,57)+65).chr(rand(0,57)+65).chr(rand(0,57)+65).‘.txt‘; for($i=0;$i<108000;$i++) { $n=rand(0,57)+65; $s = $s.chr($n); } //write s to a file file_put_contents($fname,$s); $result = file_get_contents($fname); echo $result; |
NodeJs代码 server.js:
//server.js var http = require(‘http‘); var server = http.createServer(handler); function handler(request, response) { //console.log(‘request received!‘); response.writeHead(200, {‘Content-Type‘: ‘text/plain‘}); s=""; //generate a random string of 108KB and a random filename fname = String.fromCharCode(Math.floor(65 + (Math.random()*(122-65)) )) + String.fromCharCode(Math.floor(65 + (Math.random()*(122-65)) )) + String.fromCharCode(Math.floor(65 + (Math.random()*(122-65)) )) + String.fromCharCode(Math.floor(65 + (Math.random()*(122-65)) )) + ".txt"; for(i=0;i<108000;i++) { n=Math.floor(65 + (Math.random()*(122-65)) ); s+=String.fromCharCode(n); } //write s to a file var fs = require(‘fs‘); fs.writeFile(fname, s, function(err, fd) { if (err) throw err; //console.log("The file was saved!"); //read back from the file fs.readFile(fname, function (err, data) { if (err) throw err; result = data; response.end(result); }); } ); } server.listen(8124); console.log(‘Server running at http://127.0.0.1:8124/‘); |
接下来,使用Apache本身的压力测试工具进行2000请求的测试(200/s),结果还是挺惊人的:
#PHP: Concurrency Level: 200 Time taken for tests: 574.796 seconds Complete requests: 2000 #node.js: Concurrency Level: 200 Time taken for tests: 41.887 seconds Complete requests: 2000 |
事实证明NodeJs比PHP大概快上了14倍,结果是非常令人惊讶的,NodeJs杠杠的未来的Web趋势啊。尽管目前NodeJs的生态系统并未十分完善,大部分的面向数据库连接、网络接入、工具等等的模块也是尚未开发完毕,但是根据以上结果,窃以为PHP不会在Web之王的宝座上待太久了。
更新
我也对C#/mono版本进行了测试,结果非常差,大概每个请求的响应时间为40秒,可能是mono的任务库出现了问题,或者我的代码的哪里出错了吧。
namespace Benchmark { using System; using System.Web; using System.Web.UI; using System.Threading.Tasks; public partial class Default : System.Web.UI.Page { Random rnd=null; public void Page_Load(object sender, EventArgs e) { //RegisterAsyncTask(new PageAsyncTask(PerformIOasync,PerformIOasync,null,null)); rnd = new Random (); //Task.Run (new Action (PerformIOasync)); PerformIOasync (); } public async void PerformIOasync() { string s=""; //generate a random string of 108KB and a random filename string fname = rndchar() + rndchar() + rndchar() + rndchar() +".txt"; for(int i=0;i<108000;i++) { char ch=rndchar(); s += ch; } //write s to a file //file_put_contents($fname,$s); var slowTask1 = Task<string>.Factory.StartNew(()=> WriteToDisk(fname,s)); await slowTask1; var SlowTask2 = Task<string>.Factory.StartNew(()=> ReadFromDisk(fname,s)); await SlowTask2; Response.Write(SlowTask2.Result.ToString()); } private string WriteToDisk(string fname, string s){ System.IO.File.WriteAllText (AppDomain.CurrentDomain.BaseDirectory + fname, s); return ""; } private string ReadFromDisk(string fname, string s){ return System.IO.File.ReadAllText (AppDomain.CurrentDomain.BaseDirectory + fname); } private char rndchar() { return (char)rnd.Next (65, 112); } } } |
C#、PHP与NodeJs性能测试对比,布布扣,bubuko.com