codeigniter

如何加速CodeIgniter?

Friday, September 12th, 2008 | 建站攻略 | No Comments

Scaling and Optimizing your CodeIgniter Application, with Benchmarks

There’s been a few discussions recently about optimizing CodeIgniter applications to make them faster, more reliable, and scalable.
So, let’s look at some methods of doing this, with ‘real’ numbers and benchmarks.

‘Baseline’ - The Bog Standard

First of all, we need to build a little controller that does ’stuff’.
It’s not extremely intensive, but it gives us a good base to test these optimization techniques.

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);
}

And our view file is like this:

<?=$links?>
<?=str_replace('booya', 'Getting', ucwords($body))?>

So, now let’s benchmark this little app… with the default CodeIgniter settings… no caching, active record debug on.

Concurrency Level:      10
Time taken for tests:   22.206642 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      857000 bytes
HTML transferred:       665000 bytes
Requests per second:    45.03 [#/sec] (mean)
Time per request:       222.066 [ms] (mean)
Time per request:       22.207 [ms] (mean, across all concurrent requests)
Transfer rate:          37.65 [Kbytes/sec] received

So, 45.03 Requests per second, not bad… but I think we can make some changes and see that number improve.

Result Looping

First off, let’s change:

foreach ($query->result_array() as $page):

to:

$pages = $query->result_array();
foreach ($pages as $page):

Let’s have a look at the performance difference:

Concurrency Level:      10
Time taken for tests:   21.391068 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      857000 bytes
HTML transferred:       665000 bytes
Requests per second:    46.75 [#/sec] (mean)
Time per request:       213.911 [ms] (mean)
Time per request:       21.391 [ms] (mean, across all concurrent requests)
Transfer rate:          39.08 [Kbytes/sec] received

So, as we can see… the improvement is very small, just 1.75 request/second quicker…
But they do all add up, so make sure you take a note of this optimization and use it from now on.

Memcache

Now, onto Memcache, the ‘king’ of caching objects, arrays, you-name-it, in PHP

I start up the memcache service, then change the controller code accordingly:

$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);

Now, let’s run the benchmark to see how this improves things.

Concurrency Level:      10
Time taken for tests:   17.124866 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      857000 bytes
HTML transferred:       665000 bytes
Requests per second:    58.39 [#/sec] (mean)
Time per request:       171.249 [ms] (mean)
Time per request:       17.125 [ms] (mean, across all concurrent requests)
Transfer rate:          48.82 [Kbytes/sec] received

Well, it’s faster, but not by much… I wonder how an opcode cache could improve things?

eAccelerator

eAccelerator is an opcode cache extension for php… basically, the way that it works in ’stupid’ terms is like this:

  1. We write our application in code (almost english)
  2. We ‘execute’ the code (by running the request)
  3. PHP converts our code into another language (machine-code… let’s call it matrix-esque)
  4. PHP the executes the matrix-esque code

eAccelerator interrupts just after PHP converts our code to its machine code and ‘caches’ it, so next time, it can skip the whole translation phase of execution.
Pretty simple huh?

Lets try the baseline code, with eaccelerator on the top of it.

Concurrency Level:      10
Time taken for tests:   10.122468 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      857000 bytes
HTML transferred:       665000 bytes
Requests per second:    98.79 [#/sec] (mean)
Time per request:       101.225 [ms] (mean)
Time per request:       10.122 [ms] (mean, across all concurrent requests)
Transfer rate:          82.59 [Kbytes/sec] received

Now, that’s more like it… here we’re still doing our SQL queries, and rendering all the data dynamically, but just caching the machine code, with a drastic improvement.

CodeIgniter Output Cachining

My main reason for doing this test was just to show off one of the features that I love most in CI, output caching.
Let’s see how well full-output caching works in CodeIgniter…

Some people believe that the overhead involved in writing the cache file outweighs the speed increase of actually rendering from a cache file.

$this->output->cache(3600);

Now we run our benchmark again, (baseline code, with the output caching on) and see if there’s a difference.

Concurrency Level:      10
Time taken for tests:   6.221538 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      857000 bytes
HTML transferred:       665000 bytes
Requests per second:    160.73 [#/sec] (mean)
Time per request:       62.215 [ms] (mean)
Time per request:       6.222 [ms] (mean, across all concurrent requests)
Transfer rate:          134.37 [Kbytes/sec] received

So, the difference huge, serving 160.73 requests per second, that’s a massive improvement… but I’m not going to stop there!

Output Caching + eAccelerator

How about the ultimate? - Output caching, and opcode caching! - eAccelerator with CI Output caching:

Concurrency Level:      10
Time taken for tests:   2.565136 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      857000 bytes
HTML transferred:       665000 bytes
Requests per second:    389.84 [#/sec] (mean)
Time per request:       25.651 [ms] (mean)
Time per request:       2.565 [ms] (mean, across all concurrent requests)
Transfer rate:          325.91 [Kbytes/sec] received

Who’s the daddy then?

CodeIgniter!

For those of you struggling to digest those numbers… here’s a pretty little graph (made with codeigniter… yeah, I’m hardcore!)

CodeIgniter Benchmark Results

Further Notes

As requested, here’s the results from a couple of other tests.

First off, serving the exact same output as static index.html:
1834.95 Requests per second… Amazingly fast.

And, replacing:

foreach ($query->result_array() as $page):
$links .= '<a href="'.site_url($page['uri']).'">';
$links .= ucwords($page['title']).'</a><br />';
endforeach;

with:

foreach ($query->result() as $page):
$links .= '<a href="'.site_url($page->uri).'">';
$links .= ucwords($page->title).'</a><br />';
endforeach;

Produces 46.19 [#/sec] (mean)…. again, a slight improvement over using arrays..
But hell, I love arrays!

Elliot

Tags:

codeigniter1.7升级

Thursday, September 4th, 2008 | 胡谈互联网 | No Comments

Codeigniter出最新版本1.7.改进了一些bug,并对form验证class做了较大调整,建议更新现有程序中的相关代码。session的class也有调整,如果你用数据库保存session,那么还需要新增一行数据,来满足1.7的改进。

Version 1.7

Release Date: In development
SVN Revision: XXXX

* Libraries
o Added a new Form Validation Class. It simplifies setting rules and field names, supports arrays as field names, allows groups of validation rules to be saved in a config file, and adds some helper functions for use in view files. Please note that the old Validation class is now deprecated. We will leave it in the library folder for some time so that existing applications that use it will not break, but you are encouraged to migrate to the new version.
o Updated the Sessions class so that any custom data being saved gets stored to a database rather than the session cookie (assuming you are using a database to store session data), permitting much more data to be saved.
o Added the ability to store libraries in subdirectories within either the main “libraries” or the local application “libraries” folder. Please see the Loader class for more info.
o Added the ability to assign library objects to your own variable names when you use this->load->library(). Please see the Loader class for more info.
o Changed the output of the profiler to use style attribute rather than clear, and added the id “codeigniter_profiler” to the container div
* Helpers
o Added several new “setting” functions to the Form helper that allow POST data to be retrieved and set into forms. These are intended to be used on their own, or with the new Form Validation Class.
o Added current_url() and uri_segments() to URL helper.
o Improved accuracy of calculations in Number helper.
o Removed added newlines (”\n”) from most form and html helper functions.
o Tightened up validation in Date Helper human_to_unix(), and eliminated the POSIX regex.
o Updated Date Helper to match the world’s current time zones and offsets.
o Fixed the spelling of “raspberry” in config/smileys.php
* Other changes
o Improved performance and accuracy of xss_clean(), including reduction of false positives on image/file tests.
o Added a few openxml document mime types, and an additional mobile agent to mimes.php and user_agents.php respectively.
o Added sanitization in xss_clean() for a deprecated HTML tag that could be abused in user input in Internet Explorer.
o Added PHP Style Guide to docs.

Bug fixes for 1.7.0

* Fixed bug in xss_clean() that could remove some desirable tag attributes.
* Fixed assorted user guide typos or examples (#4807, #4812, #4840, #4862, #4864, #4899, #4930, #5006, #5071).
* Fixed an edit from 1.6.3 that made the $robots array in user_agents.php go poof.
* Fixed a bug in the Email library with quoted-printable encoding improperly encoding space and tab characters.
* Modified XSS sanitization to no longer add semicolons after &[single letter], such as in M&M’s, B&B, etc.
* Modified XSS sanitization to no longer strip XHTML image tags of closing slashes.

Tags:

CI和Jquery

Wednesday, August 13th, 2008 | 好玩的网站, 胡谈互联网 | No Comments

CI的全称叫:codeigniter

Jquery就叫Jquery

你可以用CI敏捷开发php框架下的网站,class类已经封装,银弹已经整装待发,自我扩展便捷,最关键的是CI的逻辑类似Ruby,通过URI的路径来自动解析对应的处理文件与函数,Ruby是敏捷之祖,用php来玩敏捷感觉更棒。CI的学习成本很低,开发效率很高,是轻量级网站开发的首选。我将以身作则,写一篇《CI建站2小时全攻略》,分享我做ddurl网站的经验。

Jquery也是大名鼎鼎的JS框架,封装了很好很强大的前台交互函数,等待着2.0簇拥们的顶礼膜拜。简单到极致的ajax请求,丰富的各类插件效果,小巧实用的身材,学习起来还不怎么累,满是新鲜可人的范例和教程,我想未来的网络编程将越来越傻瓜化。

试想所有的功能都封装好,只需你做好html+css的前台设计,联调一下各功能的内部衔接和数据库的写读,顺便再结合下云计算机的全球分布和带宽,网络编程将实现无本地化版本的在线联调开发,在这体系的网站将会互相连接,不仅仅只是链接,而是从功能交互到数据结构的联系,多么美好,多么强大。

我想随着google的API,以及各大网站平台的开放化,这样的愿景将触目可待。

Tags: ,

申请本站友情链接

Search