Change is in the air…

Unfortunately I think PHP and I are going to part company. A few weeks ago I decided to try out Django and Python, I’ve never coded in Python before and I’d seen a few performance benchmarks around the place showing some amazing stats for pythons speed. Anyone that knows me, knows that I have a firm belief that if you start with something slow at the lowest level then its only going to get exponentially worse each layer above.

3 weeks in and I’m dumbfounded that at how far I’ve come, what I’ve been able to build with almost no knowledge of the language. Compared to PHP, Python is beautiful to use. You can do so much with so little code. Everything is an object so OOP isn’t optional. Building up an application can be incredibly quick as there are tons of amazing modules that add instant functionality. Unlike the vast majority of PHP projects, code seems to be much higher quality with all the modules I’ve used having extensive tests packaged with them.

Django seems very solid. The automatic admin system is one of my favourite features of Django. It’s nice to have fun coding again, and Python and Django are certainly making it fun. Maybe if I get some time at a later date I’ll rip out wordpress and roll my own blog or possibly put Mezzanine through its paces.

libevent-2.0.so.5: cannot open shared object file: No such file or directory

When installing Memcached on a machine I came across the following error when I tried to start it:

memcached: error while loading shared libraries: libevent-2.0.so.5: cannot open shared object file: No such file or directory

The solution for this on Debian/Ubuntu (and probably most other linux distros) is this…

On a 32 bit system:

ln -s /usr/local/lib/libevent-2.0.so.5 /usr/lib/libevent-2.0.so.5

On a 64 bit system:

ln -s /usr/local/lib/libevent-2.0.so.5 /usr/lib64/libevent-2.0.so.5

After creating the appropriate symlink for your system you should now be able to start memcached as normal:

memcached -d -u memcached_user -m 256 127.0.0.1 -p 11211

My last thoughts on Symfony2


Well I’ve been playing with Symfony2 for 3 months now and today is the day I’m officially turning my back on the Symfony project. I played around and built several small things just to see how it worked. I found it to have a brutal learning curve but maybe thats just me. Ultimately performance is what has driven my decision. I’ve heard the arguments “early optimization is one of the 7 deadly sins of programming” and “hardware is cheap”. All I have to say to both of those arguments is bollocks!

First off:

“early optimization is one of the 7 deadly sins of programming”
Sure, I can understand that – write your app, then optimize it. But your underlying framework should be absolutely optimized. If you start with a slow base guess what the outcome is going to be… a slow website/application. From what I’ve read online, Symfony2 is probably a huge performance increase over Symfony however when you strip Symfony2 down to its core framework without Doctrine or anything else and simple do:

 public function someAction() { return new Response('Hello World'); } 

I only got 950 requests per second, before adding on any baggage at all. I made a simple site, the homepage has 2 queries and thats it. 160 requests per second. Seriously? Someone posted on my other Symfony post that “you could pick another framework that is 20% faster….”, so lets look at some other frameworks for a second:

Out of the box, (H)MVC “Hello World” tests:

DooPHP: 8800 requests per second
FuelPHP (5.3 framework): 5000 requests per second
Codeigniter 2: 4800 requests per second
Kohana: 4000 requests per second
Yii: 3900 requests per second
Cake: 1300 requests per second

All tests were done on exactly the same server, running exactly the same software stack, and all taking network out of the equation. When you added network into the equation, my server was able to deliver about 700 requests per second of a full content index page of a website, still about 5 times more than the same page built in Symfony2 using 2 doctrine queries. The test machine is a 768MB of RAM, quad processor, virtual machine from Linode.

“Hardware is cheap”
I’ve heard this argument plenty of times. Sure the hardware might be cheap but that doesnt factor in the cost of the people required to make your application run on a multi server configuration or the cost of building and configuring that hardware to work well. Building multi server deployments comes with a whole host of challenges and most people don’t have an app that can scale horizontally at the flip of a switch. Funny that all the worst performing platforms all say “hardware is cheap”. Magento is a great example of this philosophy. Quite possibly the best marketing scam ever, Magento is a joke when it comes to performance. But I digress…

Symfony2 is slow, very very slow. Regardless of caching, the core framework is more than 5 times slower than FuelPHP (another 5.3 framework). If that is the sacrifice you are willing to make then good on you. Supposing you wanted to service hundreds of thousands of requests per day. With a performance driven framework you could do it with a single dedicated box which for arguments sake costs you $200 per month. With Symfony you’d be looking at $1000 per month. Thats an awful lot of additional tshirts, coffee mugs, or iphone apps that you’d have to sell each month just to pay your hosting (let alone the more specialised staff for multi server setups).

TL:DR
Symfony2, can I please get a credit for the last 3 months of my life. Thanks.

My first thoughts on Symfony2

I’ve been playing with Symfony2 for a little while now and I think I’m starting to get on top of it. When I started looking at Symfony2 I’d never used an ORM or a templating language before as well as not being versed in the features that PHP 5.3 introduced to the language. All in all it has been a very steep learning curve for me. If you are new to PHP frameworks or object oriented PHP then you can expect to feel thoroughly overwhelmed at first and it will take a lot of hours to produce something functional.

Having said all that – now that I’m starting to get my head around Symfony and I’ve made a few small basic apps, it really is quite a nice framework to code in. I really like the bundle system because it encourages you to make things in a reusable way. I can see in a few months that I will have my own bundle of bundles and that developing an app will be significantly faster as I’ll be able to drop in large amounts of functionality very very quickly.

I’m concerned about the performance of Symfony. It has the nick name “slowfony” for version 1 amongst performance oriented developers. I did some initial tests with caching completely disabled and the results were pretty bad. Even with APC I was only seeing 130 requests per second without hitting the database. I really need to spend more time understanding the caching aspects of Symfony so I can write a post on maximising performance.

How to stop Joomla Media Manager making your image names lowercase!

I recently developed a simple module that loaded in images automatically based off a folder/file structure in the images folder. The name of the file would dictate the caption underneath the image requiring names of files to be descriptive and capitalized correctly. I didn’t realise at the time I built this module that Media Manager converts all filenames to lowercase by default. I did a quick Google and found several people asking how to switch this off but no answers.

I needed to switch this off so I did some quick searches of the admin folder and found the answer.

Open the file:
/administrator/components/com_media/controllers/file.php

If you do a search in the file for ‘strtolower’ you should find a line of code that looks like this:
(line 58 in the version of Joomla 1.5 I was working on)

$filepath = JPath::clean(COM_MEDIA_BASE.DS.$folder.DS.strtolower($file['name']));

Simply change this line to look like this:

$filepath = JPath::clean(COM_MEDIA_BASE.DS.$folder.DS.$file['name']);

And thats all there is to it. Now you can have any capitalization at all in your filenames.

DISCLAIMER: I strongly recommend not doing this as it is a core component, if you decided to do this as you have no option then at least make a note of it because next time you upgrade Joomla this change will more than likely be overridden.

PHP-FPM crashes using PHP 5.3.6 with Nginx

I recently spent a few hours smashing my head against my keyboard trying to figure out why PHP-FPM was dying every time I tried to load my favourite framework. The cause ended up being APC. Versions 3.1.9 and 3.1.8 don’t work properly with PHP 5.3.6 on Ubuntu 10.04 and Debian 6. I had to use APC 3.1.6 to get it to compile without errors.

Hope this saves someone an hour or two.

Rewriting subdomains to the Document Root in Nginx

I spent a little bit of time on this today getting my development environment working this morning on my new laptop. I wanted to be able to create a new folder inside a directory and not have to create a Nginx config each time.

This is just a minimal conf and you can add in all the whistles and bells that you like. The part that had me stuck was setting the variable. The searches I originally did showed the config working without having to set a variable, just using $1 from the regex in the root value. Once I set the variable and replaced the variable in the root directive it all fell into place.

Hope this helps someone 🙂

server {
    
    server_name ~^(.+).example.com$;
    
    set $file_path $1;
        
    root    /home/$file_path/public_html;
    index   index.html index.php;

    location / {
        try_files $uri /$uri /index.php?$args;
    }
    
    location ~ .php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        /usr/local/nginx/conf/fastcgi_params;
    }
    
}

Iptables Rules to allow Git

I have a client that wanted to use Git on their VPS. My firewall was blocking it and I had to do a little research. Git uses port 9418 to communicate. You don’t want to open up the port externally so I used stateful inspection to open the port only if we established the connection.

Here are the iptables rules:

# allow git
iptables -A OUTPUT -o eth0 -p tcp --dport 9418 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth0 -p tcp --sport 9418 -m state --state ESTABLISHED -j ACCEPT

Ubuntu 11.04 libjpeg.so libpng.so PHP installation issues

I purchased a new laptop today. After about a week of research and looking at various options I decided on an HP DV6-6026TX. So for the laptop has been an absolute joy to work with. The first thing I did was blow away Windows completely and install Ubuntu 11.04. The first thing I discovered was that if you install the genuine ATI graphics drivers, Unity dies. Ubuntu installed straight away and everything I’ve tested (which isnt that much) seems to be working fine.

So, first thing to do is get the machine all setup as a development platform for my study/work. I installed Nginx and then started getting PHP ready to install. Once I was all ready to go I started the ./configure script for PHP. The configuration script fails with warnings about libjpeg.so. I immediately changed my ./configure to have:

--with-jpeg-dir=/usr/lib/x86_64-linux-gnu

Unfortunately this failed as well which did surprise me. My solution to the problem was to create symlinks for both libjpeg.so and libpng.so to the /usr/lib directory and to only have --with-jpeg-dir in my configure script.

In summary, here are the 2 simlinks that were required when building PHP on Ubuntu 11.04 64bit:

ln -s /usr/lib/x86_64-linux-gnu/libjpeg.so /usr/lib/libjpeg.so
ln -s /usr/lib/x86_64-linux-gnu/libpng.so /usr/lib/libpng.so

Unable to allocate memory pool.

When you wake up in the morning, log into your web server and glimpse at your php error logs it can be a little unsettling to see every page request producing ‘Unable to allocate memory pool’ error messages. After doing some googling and reading the APC bug list I found lots of people are experiencing this problem. I was experiencing this issue myself and needed a solution fast. I scrolled down through the comments and discovered that the general consensus was to set:

apc.mmap_file_mask = /dev/zero

I decided to continue reading up on APC having made this change however a few days later MySQL randomly died. A few days later the same thing happened again. At this point I decided to revisit how I had my memory settings configured on my server. I dropped my kernel.shmmax down to about 25% of my VPS’s total amount of RAM. One thing I hadn’t used or paid much attention to is apc.php which comes with APC. I copied this to somewhere that I could browse to on my web server and looked at the stats of my cache. It became immediately apparent what was occurring – my cache was becoming so fragmented and full of stale data that there was nowhere that the cache could use.

That’s when I decided to read about the various TTL settings for APC.


The number of seconds a cache entry is allowed to idle in a slot in case this cache entry slot is needed by another entry. Leaving this at zero means that APC's cache could potentially fill up with stale entries while newer entries won't be cached. In the event of a cache running out of available memory, the cache will be completely expunged if ttl is equal to 0. Otherwise, if the ttl is greater than 0, APC will attempt to remove expired entries.

I then looked at Rasmus’s example of php.net and looked at his APC settings. I noticed he had apc.ttl = 0 and that apc.user_ttl = 600 and apc.gc_ttl = 600. I made those changes to my own configuration and haven’t had an issue since. The site is significantly faster than it was with apc.ttl set to a fixed amount and I’d rather the cache flushed itself and started rebuilding itself rather than have the cost of defragmenting the cache each page request. I’m no authority on the matter but I know what worked for me.

I’ve since changed my apc.mmap_file_mask back to:

apc.mmap_file_mask = /tmp/apc.XXXXXX

and am monitoring how my server runs. If I have any updates I’ll let you all know.

Edit: I’ve been running with this config setup for 9 months or so now and it is running like a dream. I highly recommend having apc.ttl = 0, you can set your apc.user_ttl to whatever is appropriate for your caching setup and apc.mmap_file_mask = /tmp/apc.XXXXXX