Welcome Guest, Not a member yet? Register   Sign In
What are your performance best-practices?
#1

[eluser]kilishan[/eluser]
I recently stumbled across DooPHP a new PHP framework, which claims to be "one of the fastest, if not the fastest PHP framework available." I've always been aware of the performance of my apps, though my knowledge in that area isn't what I wish it might be. Their benchmarks make some pretty bold claims so I downloaded it and tested it myself. The results were very surprising.

Using their base app I am averaging 1100 request/second with XCache enabled. Comparing that to a bare-bones install of CodeIgniter running Ocular to show the welcome screen I'm only averaging around 240 rps. That's a drastic difference. Comparing it to a large site that I'm just finishing up, and the results are even more impressive. Granted, though, there's a lot of information getting pulled for the front page of my latest site.

It did get me really thinking about performance, though. What can we do to make our CI sites run faster, just based on our coding style and software design?

The first thing that comes to mind is the sheer number of files that we're loading. Every model, library, config file, etc takes time to find and memory to load. Is it possible to combine related models into a single file to reduce a little of that? For example, on a simple forum I've written, there's 4 model files, all related. One each for categories, topics, replies, and favorites. Now, they're all based off of a Base_model class, so that helps with memory because all of the common functions are only loaded into memory once, but it is a file. If I can reduce those 4 files into a single file, I'm thinking there might be a small performance boost there, but I don't know if I'd need to combine them all into one class or not.

I don't have the answers here. I guess I'm mostly thinking out loud. I am going to try this with Ocular and theCloset, though, just to see if they have any measurable affect or not. If it does, I'll release an OcularPlus library that has the asset management included.

I do want to hear your ideas, though. What do you do to help keep your performance optimized? Know any best practices or tips? If so, please share them in the comments.
#2

[eluser]Cro_Crx[/eluser]
DooPHP requires PHP 5.1.x or newer. CodeIgniter runs on PHP4x. Having to cater for older versions of PHP means that some things aren't written as efficiently as possible and so you loose some performance. Also the more features you put into a framework, the slower it's going to be. I had a quick look at DooPHP and can see that they have an ORM layer and a tempting engine which is nice, although didn't look to see what else was there.

When I look at what frameworks to use, personally the documentation is the first thing I look at. There's no point of having a framework if no one can show you how to use it. A PHP Framework should provide you with a quick development time, if the documentation isn't good then this won't be the case. I use CodeIgniter and jQuery for most projects as they have awesome documentation. Developing an application as best and as rapidly as possible is the best approach. If the framework is "quick enough" then it's good enough.

If your application can do 240 requests per second. Thats 864 000 per hour and 20 736 000 per day. Yes 20 million per day. If you can manage to pull in 20 million hits per day then i'm sure you could spend the money on a quicker server.

By all means go checkout DooPHP. If their documentation was a bit nicer I probably would myself as well. Although I wouldn't use it just because it's faster if it's lacking features or takes longer to develop applications for.
#3

[eluser]kilishan[/eluser]
I don't have any real interest in switching, and wasn't trying to get a 'framework war' started. It just really got me thinking about programming styles that will optimize our CodeIgniter website. Frankly, their docs suck, and I totally agree with you. CodeIgniter and jQuery are the tools I personally use, also, and it is in large part because of their docs.

As for the hits, that's a raw welcome page on the CI test with no database access, etc. I'm not worried about being able to handle a sustained 200+ requests/second, just knowing that the site can do it's best to withstand being Dugg or the Slashdot effect. I know that I've also read articles, though I can't find them right now, talking about the percentage of people that leave sites based on performance, and the amount of performance differences in their studies were pretty miniscule. So, to me, it seems like this is something that I should be concerned about within reason, if only for my client's sake.

What I was hoping to get, though was some tips and best-practices as far as CI is concerned to eek every bit of speed out of the site that I can. Currently, all of my sites perform 'good enough'. I guess I'm just not satisfied with that answer. Smile
#4

[eluser]Cro_Crx[/eluser]
Quote:I don’t have any real interest in switching, and wasn’t trying to get a ‘framework war’ started.

Sorry if it seemed I was implying that you were. That wasn't my intention.

There's probably not that much you could do to speed up base codeIgniter install. The framework is still going to load all of the base models + check routes + hooks + everything else. The speedups you are going to gain are going to be how you build your application from the base framework. There's plenty of things to do to make sure that your application is as quick as possible, simple things like:

* Grouping similar queries for pages and limiting the amount of queries per page
* Only getting relevant information from the database. Don't pull a whole row when you only need one field.
* Use a database caching system (Memcached)
* Use a Opcode Cache for PHP (Try them all out and see which is best for your application http://en.wikipedia.org/wiki/List_of_PHP_accelerators
* Write less Code!

If you're creating your own libraries you don't have to make them PHP4 compliant as well. So you can gain some extra speed by using PHP5 only.

BTW: Are you using some sort of ORM at all in your applications ?
#5

[eluser]kilishan[/eluser]
Thanks for the tips.

First, no, I'm not using any ORM. I've got a base model file that all of my models derive from that handles the basic CRUD functions with a couple of extra utility methods in there. From there, derived models are using joins and left joins where needed.

I've never actually tried using Memcached, yet, but the next project I'm on might benefit from it so I'll probably give it a try there.

One question, though, since my SQL skills are not up to Ninja levels. You said "Grouping similar queries for pages and limiting the amount of queries per page". I try to do that to the best of my abilities, and I think my heaviest page has only 8 queries (including the sessions). I've always wondered if there was a way to group unrelated queries into a single query. Say I want to pull all of the items for the footer for this site (which has the latest blog post, upcoming events, and latest site news). I have to do this for every page, so is it possible to have a single query that creates the equivalent of an associative array? Something like:

Code:
+ news
  - news item 1
  - news item 2
+ posts
  - post item 1
  - post item 2
+ events
  - event 1
  - event 2

I've never managed to make that work, though my knowledge of subqueries isn't very strong, but from what I've found so far, I don't understand how to do it, if it's even possible...
#6

[eluser]Cro_Crx[/eluser]
Quote:First, no, I’m not using any ORM

You've gotta try one out. It's like the different between using templates and not using templates. Helps heaps, although there is a bit of a learning curve. I recommend DMZ http://www.overzealous.com/dmz/ if you are going to try one, although you need to use it throughout the project so best to try it out next time you start something new. Using DMZ has cut my development time down a fair amount and now my Controllers are very short which is also nice.

In the example you gave it's not possible to group the queries together. You're going to need 3 different queries to get all your data. What I meant was that if you need to get data from the same table in multiple places you can use a single queries then break up the results later. This works well as the database is the slowest part of your application.

Luckily using DMZ allows you to get related objects without having to write any active record or SQL yourself, for example if you have news which can have many events. Let's say we want to get all the events for the news item with id of 8. All we need in the controller is:

Code:
$news = new News(8);
$news->event->get();

// Events can be accessed with $news->event->all();

Elliot has written an excellent article which I just found again. Has things to try and actual benchmark results included at every step. Really helpful Smile

http://www.haughin.com/2008/02/13/optimi...plication/

Also some stuff that's probably not AS helpful but always fun to look at http://www.phpbench.com/
#7

[eluser]Cro_Crx[/eluser]
I was just playing around with some things now. I have a page that has 9 queries or so. I ran through apache bench and managed 59.23 [#/sec] (mean).

Then changed the database driver to mysqli (instead of mysql). All recent version of MySQL support this mode. Just change this line in your config.php:

Code:
$db['default']['dbdriver'] = "mysqli";

Ran through again and now: 213.20 [#/sec] (mean) An Increase of 360%
#8

[eluser]kilishan[/eluser]
Interesting! I just gave it a try on one of my sites and didn't get but a couple rps improvement. I ran it several times, too. Hmmm.

Thanks for the pointer to Elliot's article. That's a good one. He had another good one there about scaling in general. I'll have to take some time to read through some stuff at phpbench.

I've been tempted by DMZ and IgnitedRecord a couple of times, but on these last couple of sites I didn't have the time for the learning curve. Have always been a bit worried by the performance and memory requirements, also, though I've never actually used them.
#9

[eluser]Cro_Crx[/eluser]
Strangely enough if i leave the driver as 'mysql' and turn off persistent connections I get almost the same speedup. mysqli doesn't support persistent connections so maybe this is why I get the improvement, from turning off persistent connections.

I have a solid state drive in this machine so i'm wondering if that's why there's a big difference ? Persistent connections are slower with an SSD perhaps ?

The benchmark I just ran then was for a CMS i'm building using DMZ. That particular page has 9 database calls and uses a couple of different models as well as a templating system and loads some libraries i've written. ~ 200 requests per second for that is fine by me Smile
#10

[eluser]Jamie Rumbelow[/eluser]
I think that the tradeoff between raw speed and programmer <strike>orgasms</strike> happiness is the thing that you really need to think about - after all, speed can be improved when needed to be later. Simply adding APC, some Memcached stuff at the database level and page caching can dramatically speed up your site. I believe we should generally take a more pragmatic approach to development - build the app first, then improve the performance.

As far as an ORM goes, yes, they do use more memory and can be a performance hit when not written/used correctly, but they speed up development by a huge amount. That, for me, is worth buckets more than any performance improvement.

Just my two ¢ Smile




Theme © iAndrew 2016 - Forum software by © MyBB