横向压力测试:Ruby on Rails PK CakePHP

Ruby on Rails以优雅的MVC架构闻名,这个架构如此诱人和美丽,而CakePHP则是PHP开发中常用的框架之一。如果你不想束缚于传统的PHP的砖头式开发,那么你可以尝试转向MVC架构,不过Rails的性能和部署问题一直让人担心。

两者对比的话题在网上众说纷纭,很少见到客观而有说服力的论证和充分模拟实际环境下的压力测评。作为架构选型的重要决定,我们既不能人云亦云,更不可凭空臆想,一定要有充分的测试数据才能帮助做出正确的决定。

心动不如行动,立刻着手安排了仿真环境测试。第一步是设计测试方案:

压力测试的目标集中在Ruby On Rails和CakePHP的效率,所以采用同样的Nginx生产环境,但避开所有数据库操作以避免瓶颈转嫁到数据库影响结果。

代码的主要部分都是通过输出128000个4位的十进制随机数,来模拟总计约500KB的页面数据输出。调用的指令都很基本,对脚本测试来说很公平。

不过既然是虚拟高压力测试,实际环境中数据库读写等操作的时间开销应该有一个仿真替代,所以通过Sleep 200ms来仿真具有高度数据压力的服务端。当然我们都知道Sleep是没有真实的cpu开销的,所以不会影响测试结果的公平。

测试工具使用经典的ApacheBench。先后测试10并发100请求(-c 10 -n 100) 的中等压力,和200并发5000请求(-c 200 -n 5000)高压测试。

环境

OS: FreeBSD 8.1  


CPU: Intel 4核心 Core 2  


RAM: 4GB 内存  


PHP环境:nginx+php-fpm(5.3.3)+APC  


Rails环境:nginx+passenger+Ruby(1.8.7) on Rails(3.0.0)  


所有软件均使用ports安装 

fpm的优化配置:

pm.max_children = 1000 



pm.start_servers = 20 




pm.min_spare_servers = 5 




pm.max_spare_servers = 1000 

passenger的优化配置(nginx.conf):

passenger_max_pool_size  300;//4GB内存最大的允许值,再追加便无法启动passenger

通过Rails脚本创建Test App:

rails new dummy

Ruby on Rails 代码:

// app/controller/test_controller.rb  



class TestController  ApplicationController 



  def index  


    sleep(0.2)  


  end  


end// app/views/test/index.html.rb  


% 128000.times do %>%=rand(8999)+1000%>% end %> 

PHP代码:

// vsruby.php  



php   



 


usleep(200000);  



echo "html>head>head>body>";  




for($i = 0; $i  128000;$i++)  



{  


  echo mt_rand(8999,9999);  


}  


 



echo "body>html>"; 

CakePHP代码:

// CakePHP  


// app/controller/test_controller.php  



php 



  class TestController extends AppController {  



   var $name = 'Test';  



   function index()  


   {  


    usleep(200000);  


   }  


  } // CakePHP  


// app/views/test/index.ctp  



php 




for($i = 0; $i  128000;$i++)  



{  


  echo mt_rand(8999,9999);  


}  



?> 

10并发100个请求:

// Ruby on Rails  


// CPU usage: 100%  


Server Software:        nginx/0.8.52  


Server Hostname:        127.0.0.1  


Server Port:            80  


 


Document Path:          /test/  


Document Length:        512731 bytes  


 


Concurrency Level:      10  


Time taken for tests:   40.939 seconds  


Complete requests:      100  


Failed requests:        0  


Write errors:           0  


Total transferred:      51334500 bytes  


HTML transferred:       51273100 bytes  


Requests per second:    2.44 [#/sec] (mean)  


Time per request:       4093.898 [ms] (mean)  


Time per request:       409.390 [ms] (mean, across all concurrent requests)  


Transfer rate:          1224.54 [Kbytes/sec] received  


 


Connection Times (ms)  


              min  mean[+/-sd] median   max  


Connect:        0    0   0.0      0       0  


Processing:  1231 4036 3167.1   3149   16396  


Waiting:     1203 2428 2533.7   1625   15683  


Total:       1231 4036 3167.1   3150   16396  


 


Percentage of the requests served within a certain time (ms)  


  50%   3150  


  66%   3353  


  75%   3679  


  80%   3893  


  90%  12307  


  95%  12307  


  98%  16108  


  99%  16396  


 100%  16396 (longest request)//php  


//CPU usage: 20-30%  


 


Server Software:        nginx/0.8.52  


Server Hostname:        127.0.0.1  


Server Port:            80  


 


Document Path:          /php/  


Document Length:        512039 bytes  


 


Concurrency Level:      10  


Time taken for tests:   4.144 seconds  


Complete requests:      100  


Failed requests:        0  


Write errors:           0  


Total transferred:      51218600 bytes  


HTML transferred:       51203900 bytes  


Requests per second:    24.13 [#/sec] (mean)  


Time per request:       414.389 [ms] (mean)  


Time per request:       41.439 [ms] (mean, across all concurrent requests)  


Transfer rate:          12070.36 [Kbytes/sec] received  


 


Connection Times (ms)  


              min  mean[+/-sd] median   max  


Connect:        0    0   0.1      0       0  


Processing:   400  405  14.0    403     502  


Waiting:      201  205   3.1    204     218  


Total:        400  405  14.0    403     502  


 


Percentage of the requests served within a certain time (ms)  


  50%    403  


  66%    404  


  75%    405  


  80%    405  


  90%    408  


  95%    409  


  98%    501  


  99%    502  


 100%    502 (longest request)// CakePHP  


 


Server Software:        nginx/0.8.52  


Server Hostname:        127.0.0.1  


Server Port:            80  


 


Document Path:          /cakephp/  


Document Length:        512652 bytes  


 


Concurrency Level:      10  


Time taken for tests:   4.036 seconds  


Complete requests:      100  


Failed requests:        0  


Write errors:           0  


Total transferred:      51291900 bytes  


HTML transferred:       51265200 bytes  


Requests per second:    24.78 [#/sec] (mean)  


Time per request:       403.553 [ms] (mean)  


Time per request:       40.355 [ms] (mean, across all concurrent requests)  


Transfer rate:          12412.20 [Kbytes/sec] received  


 


Connection Times (ms)  


              min  mean[+/-sd] median   max  


Connect:        0    0   0.7      0       6  


Processing:   302  399 119.1    363     775  


Waiting:      275  370 119.9    340     764  


Total:        302  400 119.1    364     775  


 


Percentage of the requests served within a certain time (ms)  


  50%    364  


  66%    372  


  75%    378  


  80%    381  


  90%    725  


  95%    755  


  98%    775  


  99%    775  


 100%    775 (longest request) 

5000个请求,200并发数:

// php  


Server Software:        nginx/0.8.52  


Server Hostname:        127.0.0.1  


Server Port:            80  


 


Document Path:          /php/  


Document Length:        512039 bytes  


 


Concurrency Level:      200  


Time taken for tests:   82.243 seconds  


Complete requests:      5000  


Failed requests:        0  


Write errors:           0  


Total transferred:      2560930000 bytes  


HTML transferred:       2560195000 bytes  


Requests per second:    60.80 [#/sec] (mean)  


Time per request:       3289.722 [ms] (mean)  


Time per request:       16.449 [ms] (mean, across all concurrent requests)  


Transfer rate:          30408.75 [Kbytes/sec] received  


 


Connection Times (ms)  


              min  mean[+/-sd] median   max  


Connect:        0    1   1.6      0      20  


Processing:   405 3258 4830.3   2675   56787  


Waiting:      202 1048 1324.8    344   53432  


Total:        405 3259 4830.3   2676   56787  


 


Percentage of the requests served within a certain time (ms)  


  50%   2676  


  66%   3081  


  75%   3361  


  80%   3535  


  90%   3828  


  95%   4262  


  98%   5709  


  99%  31863  


 100%  56787 (longest request) // CakePHP  


 


Server Software:        nginx/0.8.52  


Server Hostname:        127.0.0.1  


Server Port:            80  


 


Document Path:          /cakephp/  


Document Length:        512652 bytes  


 


Concurrency Level:      200  


Time taken for tests:   99.652 seconds  


Complete requests:      5000  


Failed requests:        0  


Write errors:           0  


Total transferred:      2565102923 bytes  


HTML transferred:       2563767656 bytes  


Requests per second:    50.17 [#/sec] (mean)  


Time per request:       3986.073 [ms] (mean)  


Time per request:       19.930 [ms] (mean, across all concurrent requests)  


Transfer rate:          25137.36 [Kbytes/sec] received  


 


Connection Times (ms)  


              min  mean[+/-sd] median   max  


Connect:        0    4  57.8      0    1663  


Processing:   367 3969 1825.7   3857   10630  


Waiting:      280 1543 731.9   1297    3953  


Total:        472 3973 1824.8   3860   10630  


 


Percentage of the requests served within a certain time (ms)  


  50%   3860  


  66%   4466  


  75%   5065  


  80%   5426  


  90%   6482  


  95%   7337  


  98%   8599  


  99%   8847  


 100%  10630 (longest request)  


// Rails  


//约10分钟后,服务器进入假死状态。 

横向压力测试:Ruby on Rails PK CakePHP

备注:

因为不太相信ruby的性能会有这样大的差距,怀疑是否ruby的rand()效率格外的低造成问题,我在测试完成又将rand()去掉,改为直接输出数字,但脚本执行时间并没有明显缩短。所以应该说是 ruby 对循环或数据输出的处理效率不佳导致。

结论

坦白说,几个ab测试跑下来,ruby的成绩如此之差,不但10并发的100请求就已经用满了服务器资源,更甚至没有能通过200并发5000请求的高压测试,这把我自己也吓了一跳。想到坚持在使用Rails的twitter,心中的敬佩油然而生。不知道那是什么样的硬件或软件优化,才可以用Ruby来支撑那样巨大的访问量。

客观的从纯性能的角度出发,在生产环境中,Ruby/Rails还是只适合Small Business。对与压力较高的服务或应用,就必须投入大量额外的硬件资源才能维持。本次测试中,Ruby On Rails与CakePHP的性能差距达到10倍之多,实在让我不敢考虑把Rails用在生产环境中。另一方面,PHP依托庞大的社区,多年来积累了众多的优化手段,其性能领先也有它的道理。在PHP架构之上的MVC候选人CakePHP,性能虽然相对于传统php的代码书写方法略有损失,但这个损失不到10%。所以对于在考虑MVC架构的php用户来说,CakePHP的性能完全在可以接受的范围内。

相关推荐