用户
 找回密码
 入住 CI 中国社区
搜索
查看: 21287|回复: 20
收起左侧

根据基准测试来优化并调整你的 CodeIgniter 应用程序

    [复制链接]
发表于 2008-4-5 15:04:49 | 显示全部楼层 |阅读模式
作者: Elliot Haughin
翻译: Hex
原文: http://www.haughin.com/2008/02/1 ... gniter-application/


  根据基准测试来优化并调整你的 CodeIgniter 应用程序。
  最近有很多关于怎样优化 CodeIgniter 应用程序以使它们更快,更可靠并且可扩展性更强的讨论。
  所以,让我们用“真实的”数据和基准测试来了解一些实现这个目标的方法。


“基准线” - 标准情况

  首先,我们需要创建一个小的控制器作为“原材料”。
  它并不精致,但它给了我们一个很好的基础,以测试这些优化技术。
PHP复制代码
function index()
{
$query = $this->db->get('module_pages');
 
$links = '';
 
if ( $query->num_rows > 0)
{
foreach ($query->result_array() as $page):
 
$links .= '<a href="'.site_url($page['uri']).'">';
$links .= ucwords($page['title']).'</a><br />';
 
endforeach;
 
$data['links'] = $links;
}
 
for ($i=0; $i < 10; $i++)
{
$this->db->like('title', 'London');
$query = $this->db->get('module_pages', 1);
 
if ( $query->num_rows == 1 )
{
$row = $query->row_array();
$row['body'] = str_replace('Getting', 'booya', $row['body']);
 
$data['body'] = $row['body'];
}
}
 
$this->load->view('welcome2', $data);
}
复制代码

  我们的视图文件是这样的:
PHP复制代码
<?=$links?>
<?=str_replace('booya', 'Getting', ucwords($body))?>
复制代码

  现在,让我们对这个小程序进行基准测试,使用 CodeIgniter 默认设置(没有缓存,打开 Active Record 调试)。

并发级别:     10
测试花费时间:   22.206642 秒
完成请求:     1000
失败的请求:    0
写入错误:     0
总的传输量:    857000 字节
HTML 传输量:   665000 字节
每秒请求数:    45.03 [#/秒] (平均值)
每请求花费时间:  222.066 [ms] (平均值)
每请求花费时间:  22.207 [ms] (平均值,所有并发请求)
传输率:      37.65 [KB/秒] 已接收

  如此看来,每秒 45.03 个请求不赖,不过,我认为我们可以作一些修改,看看到底能有多少改善。


循环的效果

  首先,让我们修改:
PHP复制代码
foreach ($query->result_array() as $page):
复制代码

  为:
PHP复制代码
$pages = $query->result_array();
foreach ($pages as $page):
复制代码

  让我们来看看性能的不同之处:

并发级别:     10
测试花费时间:   21.391068 秒
完成请求:     1000
失败的请求:    0
写入错误:     0
总的传输量:    857000 字节
HTML 传输量:   665000 字节
每秒请求数:    46.75 [#/秒] (平均值)
每请求花费时间:  213.911 [ms] (平均值)
每请求花费时间:  21.391 [ms] (平均值,所有并发请求)
传输率:      39.08 [KB/秒] 已接收

  我们可以看到改善非常小,只快了 1.75 个请求/秒。
  但这么做确实有提升,所以一定要注意这个优化,并从现在开始使用它。


Memcache

  现在来谈谈 Memcache — PHP 对象、数组和其他内容的最强缓存工具。
  启动 memcache 服务,然后相应的修改控制器的代码为:
PHP复制代码
$memcache = new Memcache;
$memcache->connect('localhost', 11211) or die ("Could not connect");
$data = $memcache->get('view_data');
 
if ( !$data )
{
$query = $this->db->get('module_pages');
 
$links = '';
 
if ( $query->num_rows > 0)
{
$pages = $query->result_array();
 
foreach ($pages as $page):
 
$links .= '<a href="'.site_url($page['uri']).'">';
$links .= ucwords($page['title']).'</a><br />';
 
endforeach;
 
$data['links'] = $links;
}
 
for ($i=0; $i < 10; $i++)
{
$this->db->like('title', 'London');
$query = $this->db->get('module_pages', 1);
 
if ( $query->num_rows == 1 )
{
$row = $query->row_array();
$row['body'] = str_replace('Getting', 'booya', $row['body']);
 
$data['body'] = $row['body'];
}
}
 
$memcache->set('view_data', $data, false, 3600) or die ("Failed to save data at the server");
}
 
$this->load->view('welcome2', $data);
复制代码


  现在,让我们运行基准测试,看看有什么提高的地方。

并发级别:     10
测试花费时间:   17.124866 秒
完成请求:     1000
失败的请求:    0
写入错误:     0
总的传输量:    857000 字节
HTML 传输量:   665000 字节
每秒请求数:    58.39 [#/秒] (平均值)
每请求花费时间:  171.249 [ms] (平均值)
每请求花费时间:  17.125 [ms] (平均值,所有并发请求)
传输率:      48.82 [KB/秒] 已接收

  好了,它更快了,但很有限。接下来我想知道使用一个 opcode 缓存能有多大改善?


eAccelerator

  eAccelerator 是一个 PHP 的 opcode 缓存扩展,它看起来“傻”的工作方式是:
  • 我们编写应用程序的代码(一般用英语)
  • 我们“执行”代码(通过运行请求)
  • PHP 转换我们的代码为另一种语言(机器码等,让我们称它为 matrix-esque)
  • PHP 执行 matrix-esque 代码

  eAccelerator 在 PHP 转换我们的代码为机器码的过程中,把机器码“缓存”起来,所以下次使用时,它可以跳过转换直接执行。
  很简单吧?呵呵~
  让我们使用 eaccelerator 再次测试基准代码。

并发级别:     10
测试花费时间:   10.122468 秒
完成请求:     1000
失败的请求:    0
写入错误:     0
总的传输量:    857000 字节
HTML 传输量:   665000 字节
每秒请求数:    98.79 [#/秒] (平均值)
每请求花费时间:  101.225 [ms] (平均值)
每请求花费时间:  10.122 [ms] (平均值,所有并发请求)
传输率:      82.59 [KB/秒] 已接收

  现在,他的表现越来越好了。在这里,我们一直运行 SQL 查询,并动态渲染所有的数据,但是,只缓存机器码性能就已经得到了很大的改善。


CodeIgniter 输出缓存

  我做这个测试的主要原因就是想展示一下 CI 中我最喜欢的特性 - 输出缓存。
  让我们看看,在 CodeIgniter 中怎样使用输出缓存。
  许多人认为在头部包含缓存文件的速度超过了缓存文件实际的读取速度。
PHP复制代码
$this->output->cache(3600);
复制代码

  现在再次运行我们的基准测试,(基准代码,打开输出缓存)并看看有什么不同。

并发级别:     10
测试花费时间:   6.221538 秒
完成请求:     1000
失败的请求:    0
写入错误:     0
总的传输量:    857000 字节
HTML 传输量:   665000 字节
每秒请求数:    160.73 [#/秒] (平均值)
每请求花费时间:  62.215 [ms] (平均值)
每请求花费时间:  6.222 [ms] (平均值,所有并发请求)
传输率:      134.37 [KB/秒] 已接收

  好了,差别还是很大的,达到每秒 160.73 个请求,这是一个令人印象深刻的改善,但是我不会就此罢手!


输出缓存 + eAccelerator

  如何终极优化? - 输出缓存和 opcode 缓存! - eAccelerator 和 CI 输出缓存:

并发级别:     10
测试花费时间:   2.565136 秒
完成请求:     1000
失败的请求:    0
写入错误:     0
总的传输量:    857000 字节
HTML 传输量:   665000 字节
每秒请求数:    389.84 [#/秒] (平均值)
每请求花费时间:  25.651 [ms] (平均值)
每请求花费时间:  2.565 [ms] (平均值,所有并发请求)
传输率:      325.91 [KB/秒] 已接收

  那么,谁才是老爸?
  CodeIgniter!
  为了帮你理解这些数字,我做了一个图表(用 codeigniter 制作的,是的,我是它的粉丝!)
benchmark_results1.png


进一步说明

  这里有两个其他测试的结果。
  第一个是用相同内容的静态 index.html:每秒 1834.95 个请求,快的令人惊讶!
  另外一个是把:
PHP复制代码
foreach ($query->result_array() as $page):
$links .= '<a href="'.site_url($page['uri']).'">';
$links .= ucwords($page['title']).'</a><br />';
endforeach;
复制代码

  替换为:
PHP复制代码
foreach ($query->result() as $page):
$links .= '<a href="'.site_url($page->uri).'">';
$links .= ucwords($page->title).'</a><br />';
endforeach;
复制代码

  重新测试:46.19 [#/秒] (平均值),比使用数组略有改善。
  但我就是喜欢数组!
发表于 2014-8-30 00:07:29 | 显示全部楼层
并发级别:     10
测试花费时间:   17.124866 秒
完成请求:     1000
失败的请求:    0
写入错误:     0
总的传输量:    857000 字节
HTML 传输量:   665000 字节
每秒请求数:    58.39 [#/秒] (平均值)
每请求花费时间:  171.249 [ms] (平均值)
每请求花费时间:  17.125 [ms] (平均值,所有并发请求)
传输率:      48.82 [KB/秒] 已接收
这些是怎么输出的呢 .
发表于 2018-8-15 10:09:38 | 显示全部楼层
请问这种测试所花的时间数据是用的什么工具呀?
发表于 2018-8-15 10:09:26 | 显示全部楼层
请问这种测试所花的时间数据是用的什么工具呀?
 楼主| 发表于 2008-4-8 18:01:18 | 显示全部楼层
顶。。。。。。。
发表于 2008-4-12 14:03:46 | 显示全部楼层
好像还是有点慢。。。

     不过还可以。。只是慢一点点。。
发表于 2008-12-7 22:32:19 | 显示全部楼层
再快也没有static html快
发表于 2010-4-6 09:22:32 | 显示全部楼层
速度是与生俱来的
发表于 2010-7-21 17:18:00 | 显示全部楼层
性能,顶
发表于 2010-7-26 17:03:22 | 显示全部楼层
永远不要抱怨CPU太慢,记住:只要功率够,砖头都能飞!!!——from 《感悟设计》
发表于 2010-11-2 10:34:33 | 显示全部楼层
请问这里的基准测试是用什么工具的?
发表于 2010-11-16 18:14:36 | 显示全部楼层
嗯 分析的很清晰,不错收藏下!
发表于 2011-5-9 21:54:42 | 显示全部楼层
顶!!!!!!!

本版积分规则