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

开发 后端
文章介绍了PHP开发中常用框架CakePHP与著名的MVC框架Ruby on Rails的横向压测,压力测试的目标集中在Ruby On Rails和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)高压测试。

环境

  1. OS: FreeBSD 8.1  
  2. CPU: Intel 4核心 Core 2  
  3. RAM: 4GB 内存  
  4. PHP环境:nginx+php-fpm(5.3.3)+APC  
  5. Rails环境:nginx+passenger+Ruby(1.8.7) on Rails(3.0.0)  
  6. 所有软件均使用ports安装 

fpm的优化配置:

  1. pm.max_children = 1000 
  2. pm.start_servers = 20 
  3. pm.min_spare_servers = 5 
  4. pm.max_spare_servers = 1000 

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

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

通过Rails脚本创建Test App:

rails new dummy

Ruby on Rails 代码:

  1. // app/controller/test_controller.rb  
  2. class TestController < ApplicationController 
  3.   def index  
  4.     sleep(0.2)  
  5.   end  
  6. end// app/views/test/index.html.rb  
  7. <% 128000.times do %><%=rand(8999)+1000%><% end %> 

PHP代码:

  1. // vsruby.php  
  2. php   
  3.  
  4. usleep(200000);  
  5. echo "<html><head>head><body>";  
  6. for($i = 0; $i < 128000;$i++)  
  7. {  
  8.   echo mt_rand(8999,9999);  
  9. }  
  10.  
  11. echo "body>html>"; 

CakePHP代码:

  1. // CakePHP  
  2. // app/controller/test_controller.php  
  3. php 
  4.   class TestController extends AppController {  
  5.    var $name = 'Test';  
  6.    function index()  
  7.    {  
  8.     usleep(200000);  
  9.    }  
  10.   } // CakePHP  
  11. // app/views/test/index.ctp  
  12. php 
  13. for($i = 0; $i < 128000;$i++)  
  14. {  
  15.   echo mt_rand(8999,9999);  
  16. }  
  17. ?> 

#p#

10并发100个请求:

  1. // Ruby on Rails  
  2. // CPU usage: 100%  
  3. Server Software:        nginx/0.8.52  
  4. Server Hostname:        127.0.0.1  
  5. Server Port:            80  
  6.  
  7. Document Path:          /test/  
  8. Document Length:        512731 bytes  
  9.  
  10. Concurrency Level:      10  
  11. Time taken for tests:   40.939 seconds  
  12. Complete requests:      100  
  13. Failed requests:        0  
  14. Write errors:           0  
  15. Total transferred:      51334500 bytes  
  16. HTML transferred:       51273100 bytes  
  17. Requests per second:    2.44 [#/sec] (mean)  
  18. Time per request:       4093.898 [ms] (mean)  
  19. Time per request:       409.390 [ms] (mean, across all concurrent requests)  
  20. Transfer rate:          1224.54 [Kbytes/sec] received  
  21.  
  22. Connection Times (ms)  
  23.               min  mean[+/-sd] median   max  
  24. Connect:        0    0   0.0      0       0  
  25. Processing:  1231 4036 3167.1   3149   16396  
  26. Waiting:     1203 2428 2533.7   1625   15683  
  27. Total:       1231 4036 3167.1   3150   16396  
  28.  
  29. Percentage of the requests served within a certain time (ms)  
  30.   50%   3150  
  31.   66%   3353  
  32.   75%   3679  
  33.   80%   3893  
  34.   90%  12307  
  35.   95%  12307  
  36.   98%  16108  
  37.   99%  16396  
  38.  100%  16396 (longest request)//php  
  39. //CPU usage: 20-30%  
  40.  
  41. Server Software:        nginx/0.8.52  
  42. Server Hostname:        127.0.0.1  
  43. Server Port:            80  
  44.  
  45. Document Path:          /php/  
  46. Document Length:        512039 bytes  
  47.  
  48. Concurrency Level:      10  
  49. Time taken for tests:   4.144 seconds  
  50. Complete requests:      100  
  51. Failed requests:        0  
  52. Write errors:           0  
  53. Total transferred:      51218600 bytes  
  54. HTML transferred:       51203900 bytes  
  55. Requests per second:    24.13 [#/sec] (mean)  
  56. Time per request:       414.389 [ms] (mean)  
  57. Time per request:       41.439 [ms] (mean, across all concurrent requests)  
  58. Transfer rate:          12070.36 [Kbytes/sec] received  
  59.  
  60. Connection Times (ms)  
  61.               min  mean[+/-sd] median   max  
  62. Connect:        0    0   0.1      0       0  
  63. Processing:   400  405  14.0    403     502  
  64. Waiting:      201  205   3.1    204     218  
  65. Total:        400  405  14.0    403     502  
  66.  
  67. Percentage of the requests served within a certain time (ms)  
  68.   50%    403  
  69.   66%    404  
  70.   75%    405  
  71.   80%    405  
  72.   90%    408  
  73.   95%    409  
  74.   98%    501  
  75.   99%    502  
  76.  100%    502 (longest request)// CakePHP  
  77.  
  78. Server Software:        nginx/0.8.52  
  79. Server Hostname:        127.0.0.1  
  80. Server Port:            80  
  81.  
  82. Document Path:          /cakephp/  
  83. Document Length:        512652 bytes  
  84.  
  85. Concurrency Level:      10  
  86. Time taken for tests:   4.036 seconds  
  87. Complete requests:      100  
  88. Failed requests:        0  
  89. Write errors:           0  
  90. Total transferred:      51291900 bytes  
  91. HTML transferred:       51265200 bytes  
  92. Requests per second:    24.78 [#/sec] (mean)  
  93. Time per request:       403.553 [ms] (mean)  
  94. Time per request:       40.355 [ms] (mean, across all concurrent requests)  
  95. Transfer rate:          12412.20 [Kbytes/sec] received  
  96.  
  97. Connection Times (ms)  
  98.               min  mean[+/-sd] median   max  
  99. Connect:        0    0   0.7      0       6  
  100. Processing:   302  399 119.1    363     775  
  101. Waiting:      275  370 119.9    340     764  
  102. Total:        302  400 119.1    364     775  
  103.  
  104. Percentage of the requests served within a certain time (ms)  
  105.   50%    364  
  106.   66%    372  
  107.   75%    378  
  108.   80%    381  
  109.   90%    725  
  110.   95%    755  
  111.   98%    775  
  112.   99%    775  
  113.  100%    775 (longest request) 

5000个请求,200并发数:

  1. // php  
  2. Server Software:        nginx/0.8.52  
  3. Server Hostname:        127.0.0.1  
  4. Server Port:            80  
  5.  
  6. Document Path:          /php/  
  7. Document Length:        512039 bytes  
  8.  
  9. Concurrency Level:      200  
  10. Time taken for tests:   82.243 seconds  
  11. Complete requests:      5000  
  12. Failed requests:        0  
  13. Write errors:           0  
  14. Total transferred:      2560930000 bytes  
  15. HTML transferred:       2560195000 bytes  
  16. Requests per second:    60.80 [#/sec] (mean)  
  17. Time per request:       3289.722 [ms] (mean)  
  18. Time per request:       16.449 [ms] (mean, across all concurrent requests)  
  19. Transfer rate:          30408.75 [Kbytes/sec] received  
  20.  
  21. Connection Times (ms)  
  22.               min  mean[+/-sd] median   max  
  23. Connect:        0    1   1.6      0      20  
  24. Processing:   405 3258 4830.3   2675   56787  
  25. Waiting:      202 1048 1324.8    344   53432  
  26. Total:        405 3259 4830.3   2676   56787  
  27.  
  28. Percentage of the requests served within a certain time (ms)  
  29.   50%   2676  
  30.   66%   3081  
  31.   75%   3361  
  32.   80%   3535  
  33.   90%   3828  
  34.   95%   4262  
  35.   98%   5709  
  36.   99%  31863  
  37.  100%  56787 (longest request) // CakePHP  
  38.  
  39. Server Software:        nginx/0.8.52  
  40. Server Hostname:        127.0.0.1  
  41. Server Port:            80  
  42.  
  43. Document Path:          /cakephp/  
  44. Document Length:        512652 bytes  
  45.  
  46. Concurrency Level:      200  
  47. Time taken for tests:   99.652 seconds  
  48. Complete requests:      5000  
  49. Failed requests:        0  
  50. Write errors:           0  
  51. Total transferred:      2565102923 bytes  
  52. HTML transferred:       2563767656 bytes  
  53. Requests per second:    50.17 [#/sec] (mean)  
  54. Time per request:       3986.073 [ms] (mean)  
  55. Time per request:       19.930 [ms] (mean, across all concurrent requests)  
  56. Transfer rate:          25137.36 [Kbytes/sec] received  
  57.  
  58. Connection Times (ms)  
  59.               min  mean[+/-sd] median   max  
  60. Connect:        0    4  57.8      0    1663  
  61. Processing:   367 3969 1825.7   3857   10630  
  62. Waiting:      280 1543 731.9   1297    3953  
  63. Total:        472 3973 1824.8   3860   10630  
  64.  
  65. Percentage of the requests served within a certain time (ms)  
  66.   50%   3860  
  67.   66%   4466  
  68.   75%   5065  
  69.   80%   5426  
  70.   90%   6482  
  71.   95%   7337  
  72.   98%   8599  
  73.   99%   8847  
  74.  100%  10630 (longest request)  
  75. // Rails  
  76. //约10分钟后,服务器进入假死状态。 

#p#

Rails与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的性能完全在可以接受的范围内。

原文链接:http://blog.splayer.org/index.php/2010/10/performance-penalty-in-mvc-web-deployment/

所有测试源代码和nginx/php-fpm配置文件下载:http://blog.splayer.org/wp-content/uploads/2010/10/FBSD-SandBox.zip

【编辑推荐】

  1. Ruby On Rails开发教程
  2. 在Nginx上运行Ruby on Rails
  3. Ruby on Rails性能优化七剑
  4. 详细剖析Ruby on Rails配置文件

 

责任编辑:王晓东 来源: 射手科技官方博客
相关推荐

2009-08-27 10:21:22

Ruby on Rai

2009-12-16 17:07:27

Ruby on Rai

2009-08-06 09:13:36

Ruby on Rai

2009-12-14 15:30:43

安装Ruby on R

2015-10-14 17:27:18

性能

2009-12-17 14:29:50

Ruby on Rai

2009-12-16 16:37:59

Ruby on Rai

2015-10-10 11:00:05

RubyRails性能

2009-12-16 15:41:10

Ruby on Rai

2010-09-25 14:39:29

Bruce Tate

2009-12-16 17:37:31

Ruby on Rai

2009-12-17 17:37:42

Ruby on Rai

2009-12-16 15:23:33

Ruby on rai

2009-09-29 17:04:29

2013-03-28 12:42:02

RubyRails

2009-12-16 16:24:00

Ruby on Rai

2010-10-09 08:58:03

NginxRuby on Rai

2010-07-12 09:22:05

RubyRuby on rai

2009-03-30 14:40:45

Ruby on RaiRails更新Rails

2011-08-31 17:41:07

Ruby
点赞
收藏

51CTO技术栈公众号