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

日期: 2010-10-13 作者:射手科技官方博客 来源:TechTarget中国 英文

  Ruby on Rails以优雅的MVC架构闻名。这个架构如此诱人和美丽,我也是向往已久。近日正在为射手的一个新应用做系统选型,不由自主的想结束传统php的砖头式开发,而开始转向MVC架构。于是有了Rails和CakePHP 2个候选人。

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

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

  压力测试的目标集中在RoR和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 = 1000passenger的优化配置(nginx.conf)
passenger_max_pool_size  300;//4GB内存最大的允许值,再追加便无法启动passenger 通过 Rails 脚本创建 Test App.

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

  结论:

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

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

我们一直都在努力坚持原创.......请不要一声不吭,就悄悄拿走。

我原创,你原创,我们的内容世界才会更加精彩!

【所有原创内容版权均属TechTarget,欢迎大家转发分享。但未经授权,严禁任何媒体(平面媒体、网络媒体、自媒体等)以及微信公众号复制、转载、摘编或以其他方式进行使用。】

微信公众号

TechTarget微信公众号二维码

TechTarget

官方微博

TechTarget中国官方微博二维码

TechTarget中国

相关推荐