【翻译】PHP和node.js对比

当提到Web编程,在我大部分的时间里,我都是使用ASP.NET或者LAMP技术。现在,一种新的技术叫做node.js。它是一种轻量级的开发平台,在服务端运行Javascript代码,据说通过异步I/O方法提高性能。

新理论认为同步或者阻塞性I/O工作像如下所示:

I/O是Web事务中非常典型的高代价的部分。当一个请求到达Apache Web服务器的时候,服务器将请求传给PHP解释器解析成任何动态内容。现在,棘手的问题来了—假使PHP解析想要从磁盘或者数据库读取一些内容或者写一些内容,那会是整条链子上最慢的一环。当你调用PHP函数file_get_contents()的时候,服务器全部的线程都会被阻塞,直到内容被取回。服务器将不能做任何事情直到你的脚本拿到文件内容。考虑下同时从不同用户那里发起许多类似请求到你的服务器的时候将会发生什么?他们会因为线程阻塞在I/O中,服务器没有任何线程可以用来处理任务而处在等待的队列中!

node.js提出了一个独特的卖点。因为node.js在它几乎所有的函数中实现异步I/O。在上面描述的场景中,服务器中的线程将会在文件检索函数(fs.readFile)被调用后立马被释放。然后,一旦I/O读写完毕,node就会调用一个函数(早前从fs.readFile传递过来的)传递数据参数。同一时刻,珍贵的线程能被用来服务其它线程。

这就是关于node.js的理论。但是在猿工界,我不是一个能够接受新事物的人,因为node.js被吹得天花乱坠而且每个人都在用它。不,我要自己查明和验证node.js的真实情况。我想看看这个理论是否能够经受实践检验。

所以我给自己定的工作就是写两个相同的脚本来进行基准测试:一个使用PHP(发布在Apache2上),另一个使用Javascript(发布在node.js上)。测试非常简单,脚本要实现的目标如下:

  1. 接收请求。
  2. 生成一串大小为108kb的随机字符串。
  3. 将字符串写在磁盘上的一个文件中。
  4. 然后从磁盘中读回内容。
  5. 在响应流中返回字符串。

这是第一个脚本,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;
?>

然后这是第二个脚本,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个并发)。当我看到运行结束的时间统计数据,我和我的小伙伴都惊呆了:

#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

真相大白。node.js比PHP快了十四倍多!这个结果是令人惊讶的,它简明地意味着在不久的将来,node.js将会成为编写性能驱动的应用的事实标准,这是毫无疑问的!

我同意node.js的生态系统还没有广泛地发展,很多用来数据库连接、网络接入、工具类node模块正在积极地开发中。但是尽管如此,在看到这个结果之后,我们无须担心。任何花在node.js开发上的额外努力都是值得的。PHP也许仍然能保有“Web之王”的地位,但是随着node.js的到来,我觉得那种情况不会持续很长时间。

####参考

  1. https://en.wikipedia.org/wiki/Node.js
  2. http://notes.ericjiang.com/posts/751
  3. http://nodejs.org
  4. https://code.google.com/p/node-js-vs-apache-php-benchmark/wiki/Tests

####原文信息
链接:PHP vs node.js: The REAL statistics

作者:Prahlad Yeri