xgrr.de – the whole not the half

things, thoughts and stuff out of life, daily business and computer science

Archive for the ‘Software’


Apache2 + mod_fcgid + PHP = Awesome

For years now I was using PHP as a Apache module and not thinking twice about it. Easy to install not much to maintain and working reasonably well. Server too slow? Buy a new server. Recently one of our servers got really slow again with varying timeouts while serving pages. Memory shortage. No new server available I needed to make the most of it and started investigating how to decrease the memory footprint of Apache.

FastCGI was the answer. With PHP as a module installed every Apache process can take up to the maximum amount of memory you defined in php.ini plus what the Apache process needs by himself even though this process is only serving static content. With the switch to FastCGI it was possible to use the threaded version of Apache (mpm_worker). Static contents are now served really fast without need for invoking PHP at all. PHP scripts are served by calling the FastCGI IPC.

As memory is still low Apache and PHP are both configured to “die” after quite a low number of requests served. This can sometimes lead to a small delay while the processes are restarted but ensures that the memory footprint is kept low.

How did I do it? I won’t go into details on how to install Apache, mod_fcgid and PHP because there are loads of howto’s out there. Please find the configuration I’m using below. I’m using Debian and Apache, mod_fcgid and PHP are installed out of the repository. If you have a custom compiled version or different distribution your paths can differ.

Depending on your available hardware it is feasible to tweak the settings for the mpm_worker module so more concurrent clients can be served and/or the amount of requests which is handled before re-creating the thread is higher. It is also very recommended to use eAccelerator in conjunction with this setup. See my post on the topic for more information.

/etc/apache2/apache2.conf (excerpt):

<IfModule mpm_worker_module>
	StartServers           4
	ServerLimit            4
	MaxClients           128
	MinSpareThreads        8
	MaxSpareThreads       16
	ThreadsPerChild       32
	MaxRequestsPerChild  500
</IfModule>

/etc/apache2/mods-available/fcgid.conf:

<IfModule mod_fcgid.c>
	AddHandler fcgid-script .fcgi .php
	FCGIWrapper /var/www/php-fcgi-starter .php

	IdleTimeout		3600
	BusyTimeout		 300
	ProcessLifeTime		7200
	IPCConnectTimeout	  10
	IPCCommTimeout		 360
	MaxProcessCount		  15
	MaxRequestsPerProcess	  -1
	PHP_Fix_Pathinfo_Enable    1
</IfModule>

/var/www/php-fcgi-starter:

#!/bin/sh
PHPRC=/etc/php5/cgi/
export PHPRC
export PHP_FCGI_MAX_REQUESTS=250
export PHP_FCGI_CHILDREN=1
exec /usr/lib/cgi-bin/php

eAccelerator to enhance PHP performance

In my series of optimizing one of our servers I added eAccelerator to the setup to improve the performance. One of the bottlenecks of the server is unfortunately memory. Nevertheless even with small memory settings and caching to disk eAccelerator is able to enhance the performance and user experience of our websites and eCommerce platforms by 2-2.5.

Comparing Roadsend PHP to PHP/FastCGI

For some projects it might come in handy to have a pre-compiled binary shipped to the customer or run as a separate instance. I took a peek at Roadsend PHP which implemented their own engine and is able to compile PHP source into C binaries which can either run on the command line or with special compilation arguments as a FastCGI program.

But before using it productively and changing a lot of source to make it compatible with the way how Roadsend works I wanted to make sure that the promised performance bonus would be really there. I created a very crude script which does nothing more than to iterate an integer to a certain maximum and measures the time to do this.

NOTE: I know that a proper performance test looks differently and I’m aware that Roadsend PHP can put his design into the works when we deal with a lot of includes. I’ll make another test with including random files to compare if this is impacting the results.

<?php
echo “Simple iteration test to compare performance between interpreted PHP and Roadsend PHP<hr />”;

$max = 1000;
if($_GET["max"] != “” && is_numeric($_GET["max"])) {
$max = $_GET["max"];
}

$start = microtime();

for($i = 0; $i < $max; $i++) {
echo $i.”<br />”;
}

$stop = microtime();
$elapsed = $stop – $start;
echo “<hr />Script took $elapsed seconds to execute”;
?>

To the environment. I didn’t set up a clean room environment. I used my server at home with 2G of memory Athlon64 X2 and a RAID5. Nothing special but I think it resembles real-world situations perfectly (unless you setup a new box for every PHP site you build).

Apache (worker – threaded) is used for serving the requests. FastCGIs are served via mod_fcgid. PHP is also run via mod_fcgid which improved the performance of PHP dramatically so far.

Let’s get to it:

max = 1000
Roadsend PHP: 0.005817
Interpreded PHP: 0.001201

max = 10000
Roadsend PHP: 0.06846
Interpreded PHP: 0.012625

These results are not dramatically but significant. It seems that compiling PHP adds overhead to the execution.

Funambol sync problems solved

When I was playing around with Funambol last week I was brutally stopped by an Exception thrown somewhere in the code of the Funambol DS Server.

java.lang.NullPointerException
at com.funambol.server.session.SyncSessionHandler.processInitSyncMapMessage(SyncSessionHandler.java:905)
at com.funambol.server.session.SyncSessionHandler.processMessage(SyncSessionHandler.java:521)
at com.funambol.server.engine.SyncAdapter.processInputMessage(SyncAdapter.java:533)
at com.funambol.server.engine.SyncAdapter.processXMLMessage(SyncAdapter.java:254)
at com.funambol.transport.http.server.LocalSyncHolder.processXMLMessage(LocalSyncHolder.java:97)
at com.funambol.transport.http.server.Sync4jServlet.doPost(Sync4jServlet.java:399)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.funambol.transport.http.server.LogContextFilter.doFilter(LogContextFilter.java:132)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.funambol.transport.http.server.SyncResponseTimeFilter.doFilter(SyncResponseTimeFilter.java:159)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190)
at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:769)
at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:698)
at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:891)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690)
at java.lang.Thread.run(Unknown Source)

I decided to make the effort and have a look at the code. That was actually what was taking me so long to fix the problem at hand. Today I got a fix on the actual problem. The offending code is in the handling of the session. When I configured my Funambol I supplied the URI of the service I want to create which is at this point in time not the real URI. What happens during the authentication handshake is that the session is bound to this specific URI. This means that if the client requests a specific URI the server overwrites this URI with the one set in Funambol.xml and the session is only valid for this URI.

During sync it is checked if the client is authenticated which is not the case or at least not for the URI specified in the Funambol.xml. In this case a clause in the code is reached which provokes the NullPointerException stated above.

If you have this problem, make sure that the URI in your Funambol.xml file is either empty (then the URI provided by the client is taken) or that your clients use the URI which is specified.

eBooks – Be ready for the Hype with ebook-spot.de

Surely eBooks are discussed controversially in the media. On the one side you have the publishers and the authors who are afraid of losing their market. Then of course you have the papers which turnover is declining as time progresses. Nevertheless digital versions of books, papers and magazines are more and more demanded by the public. With new technology such as the Kindle by Amazon and other high-tech gadgets it is also becoming very easy to consume these digitals.

But then you want more. And there it stops. Where to get your new eBook fix? There are a lot of different sites out there. Most of them feature PDA documents optimized for hand helds. With the enforcing of the market you can easily miss good sources.

With friends of mine I started a portal which collects links to interesting offerings on the net. We already started to gather links to commercial and non-profit organizations. We’re just started a few days back and have almost 100 links together. Have a look for yourself on ebook-spot.de!

PSU RAID

2Okay you might think there was a raid at some strange gang called PSU. You could not be more wrong :) . I actually fixed my strange RAID problems this weekend by replacing the PSU with a really good one. I chose the Thermal Take Toughpower XT 750. It comes with cable management, a fancy 14cm silent fan and enough power.

The last few days I was desperate to fix my server. A drive was crashed and I ordered new ones to replace the “broken” one but it didn’t work. All new drives were failing too. In my desperation I ended up bugging the RAID vendor but they needed more information during the weekend and that was simply not fast enough for me.

Last friday I decided to replace the crappy old PSU with a fancy new one. And it did good. No more drives failing, due to the nice fan the temperature of the disks kept on falling compared to before. Overall a good result. Finally I can access my precious data again :)

A Snow Leopard on my Mac

IMG_0170[1]Yah it really pays out to study computer science and have a lot of geeks in the course. A friend of mine provided me with the beta of Snow Leopard. Of course I directly installed it and I’m flattered by its speed. Now it means waiting for the final!

Using MP3Gain to increase iPod max volume

MP3GainIn my last post I described the possibility to increase the maximum output volume on EU iPods (probably on others too but I guess they don’t have the silly 100db volume limit integrated). In my first trials I used a target volume of 103db because I read somewhere on the net that the US iPod outputs this as max volume. The volume increase wasn’t that dramatic. So I went even higher and am using 105db as target volume which does the trick for me.

To gain the best results follow this short manual:

  1. Add the songs or directories you want to alter
  2. If you have your songs organized in albums then select each album individually them, right click on them and select “Album Analysis” and repeat that for all your albums MP3Gain recognizes different folders as different albums automatically. This ensures that the overall album volume will be kept at the same level and you won’t get any tracks with a strange peak. If you only got scattered songs  skip to step 3
  3. For songs which are not organized within an album simply select them, right click and select “Track Analysis”
  4. Select all albums, right click and select “Apply Album Gain”
  5. Select all lose tracks, right click and select “Apply Track Gain”

Now your songs should be significantly louder than before. And the most intriguing charme about all of this is that you can reverse it. MP3Gain creates two new tags within the MP3 to reverse the process if that is necessary in the future. Overall nice tool.

Increase Volume on EU iPod

apple_ipod_classic_1Obviously it is not possible to increase the maximum output volume of an iPod sold in the EU due to strange laws to protection of the listeners’ ears against damage. That said there is of course a solution to the problem. After wandering around on the net and finding absolutely NO working solution which can be achieved with built-in tools I found out about MP3Gain.

With MP3Gain it is possible to change the maximum output of an MP3 lossless. So no re-encoding required. I’m currently testing it with my iPod to check which is the best volume level for the iPod… So stay tuned!

Linux: Re-Read Partition Tables

You know how it is. Just created a new partition but it is not directly regocnized by the system without a reboot. And rebooting means downtime, going to the data center thus inconvenience. There are a few tricks you can try before having to move your body physicly:

partprobe

Check if the new partition was recognize using dmesg. If that didn’t help try the following:

hdparm -z /dev/sdX

Where /dev/sdX is the device on which you created the new partition.