Archive for March, 2008

Published by Fabian on 31 Mar 2008

performance or maintenance?

I wonder what the makers of the PHP5 practice exam wanted to express with the following question:

In a general sense, which is more important: performance or maintainability of an application?

  1. performance first, maintainability second
  2. Maintainability first, performance second
  3. Maintainability
  4. Performance

Are options 1&2 for the cowards that do not dare to restrict themselves to a single answer? Or for the wise that know that a single answer is never sufficient?
Do they want to convince us that maintainability of spaghetti PHP code is not so important because its fast? Or do they want to make us better coders, reminding of the important mission to write maintainable code?

Is this question anyway valid? Is there a universal truth out there that is valid for each and every code?

So I opt for

  • Code should be written according to customer requirements.

At least this answer can never be wrong :-)

Published by Fabian on 25 Mar 2008

PHP function backporting nightmare

While reading a the ZCE certification book I came along some oddities, which I also noticed before but couldn’t get the full picture.

When looking at PHP code you will come at some point to code that looks like this:

if (function_exists('str_split')) {
  $var = str_split($input);
} else {
  // custom code taken from php.net or brain
  $var = $temp
}

The code exists, because the developer found a nice functionality on the manual, but unfortunately noticed that it requires a bleeding edge PHP version or some special modules installed. But instead making this a requirement for his application/component to run he takes one of the plenty: “what if this is not available” workarounds from php.net manual comments. However these are mostly not so good, which you cane notice because each one will get multiple corrections.

So how to do it in a better way? You might need tis functionality also somewhere else, so please don’t start code duplication.
Some comments on php.net already suggest doing that, but not all yet, so here a proposal for better maintainability:

Somewhere in you code write

if (!function_exists('str_split')) {
  function str_split($text, $split = 1) {
    // custom code taken from php.net or brain
    return $temp;
  }
}

Thats good. Nowhere in you code you need to do ifs anymore, just use the method.
But doesn’t that come with a performance hit? Yes. It comes with a hit on versions lacking the method, even worse, it comes with a hit on versions having that method.
So I do recommend to put this into an extra file, remove the if check and document that your customer has to include that file if he is running an older version (Or better, add it to troubleshooting as well under headline “I get function not defined error”).

Even better, if you are convinced of this idea now, be prepared for: PEAR::PHP_Compat which exactly is this. So for php version mismatches a solution is found. For not (yet) installed packages: do the same. Write compat method in separate file and ask the customer to either include the compat file or install the real thing from module.

My main message is: do not spoil your code with compatibility and corner case solutions. Externalize and document them.

And check the php.net comments regularly to see if somebody corrected the workaround-solution someone posted some time ago, or found a critical security issue in it or something else :-)

Published by Fabian on 20 Mar 2008

Cheap PHP certification

I am a Java guy. I like Java, thats why I also did the certifications (SCJP,SCWCD,SCBCD,SCJD) there. To prove that I like it :-)

I today considered making the Zend Certified Engineer exam as well. I think PHP has a spot in mobile applications through its large community and its maturity. There are some other languages and web frameworks out there, but I think PHP is a solid pick. In combination with the symfony framework it can fill its space, where Java cannot extend to (perhaps they will try with all that scripting additions).

But the Zend shop is interesting. I was logged into the global one. I got all the prices in US-Dollar. And the price of the exam was: 125$. I was curious what the price in Euro would be, because, you know, Dollar is quite weak at the moment. I switch to the German store…. wow: 150 Euro.
Some maths: 125 USD are about 80 Euro. 150 Euro are about 235 USD. Wow! Thats nearly 50% off in Dollar compared to Euro.

So I did order now in America. Paying USD. Got the exam code instantly. An interesting side fact is that the invoice comes from a German company….

Published by Fabian on 20 Mar 2008

if cascade

I am currently doing a code review, where I have found this nice pearl, I have to share.

I really hope that wordpress does not kill the lovely formatting :-)

        if (initialisePools()) {
            if (replicateServices()) {
                if (replicateLocations()) {
                    if (replicateLocationData()) {
                        if (replicateContacts()) {
                            if (replicatePackages()) {
                                if (replicateCustomers()) {
                                    if (replicateCompanies()) {
                                        if (replicateGroups()) {
                                            replicateUsers();
                                            ok=true;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

A shorter way to write would be:

        ok = initialisePools() && replicateServices()
             && replicateLocations() && replicateLocationData()
             && replicateContacts() && replicatePackages()
             && replicateCustomers() && replicateCompanies()
             && replicateGroups() && replicateUsers();

any other proposals?

PS: Of course things can be always done differently, so your proposal must assume that invoking the methods separately makes sense :-)

Published by Fabian on 12 Mar 2008

Another small symfony for a fast response

François describes in his blog post A small symfony for a fast response how to create a new light-weight front controller that directly serves a component.

When I developed a chat system with symfony I had the goal to highly optimize it, however I noticed that it does not make sense to hack around in symfony. I was able to shave about 10ms on my dev machine off the request time but that was quite ugly. And as database queries take up a multitude of this I left this idea alone.

But François brought me back on track. My scenario is slightly different. I have quite a lot of executeXYZ() methods in my chat action, which are quite tightly interwoven. The action this article is about is the one that retrieves all the new lines of chat the user sees. I did optimize this a lot, it takes benefit of APC cache and returns its result as application/json resopnse, with skipping the view rendering.

There a multiple reasons why I had problems with making this a component.

So I tried a different track. I scanned around the symfony code that invokes actions and came up with this action invoking front controller:

define('SF_ROOT_DIR',    realpath(dirname(__FILE__).'/..'));
define('SF_APP',         'frontend');
define('SF_ENVIRONMENT', 'prod');
define('SF_DEBUG',       false);
 
require_once(SF_ROOT_DIR.DIRECTORY_SEPARATOR.'apps'.DIRECTORY_SEPARATOR.
SF_APP.DIRECTORY_SEPARATOR.'config'.DIRECTORY_SEPARATOR.'config.php');
 
$context = sfContext::getInstance();
$action = $context->getController()->getAction('chat','get');
$action->initialize($context);
$action->executeGet();
$context->getResponse()->sendHttpHeaders();
$context->getResponse()->sendContent();

The good thing is that this does not require refactoring, which at this late stage of the project is quite error prone. Also the action code still can be used as it is. So what was left for me to do is to analyze if there is measurable benefit.

The development test

So I fired up the chat application on my development machine and used firebug to watch the response times. Interestingly there was lots of deviation (but no statistics excursion here). But I found one value occurring most of the time (about 80% of the requests) which seems to be a good baseline for comparison.

  • Through normal symfony front controller: 268 ms
  • Through development front controller: 375 ms
  • Through single action controller: 234ms

These numbers show quite interesting facts:

  1. Symfony is already highly optimized / my optimization is not good enough. just 30ms gained.
  2. The development front controller is heavy!
  3. My optimization is still worth it :-)

I chose to utilize the 30ms gained. its near to nothing, but not neglectable. Our chat usually has during daytime about 30 users online. Each of them is requesting every 2 seconds new lines (yes I am aware of Comet/AJAX Push technology. But it does not pay off in PHP according to my tests). This makes 15 requests per second, which ideally would mean maximum 66ms per request. Seeing this together with the 10% gain this brings at virtually no cost, it would be a good idea to see this on the live system.

The live test

I hoped to see also a 10% gain on the live system, but as this is optimized even more on apache, mysql and php level I was not so sure if the 2hour investment into the lightweight controller would pay off.

The system as running at the time of test with a load of 1.17 and my pc needs about 20ms to reach it.

Naturally I get more fluctuation in the firebug timings, but surprisingly I was able to identify two timings which again made up about 80% of the total results.

  • Running through the normal symfony front controller: 234ms and 250ms
  • Running through the single action front controller: 141ms and 150ms

As this shall not be a benchmark, I am quite happy with the results, even when they are more unstable. In fact that instability of the timing results, are notable. The timings through the single action controller are much more stable. while on the the normal script i have much more variation and even single occurrences of excessive timings.
When browsing through the symfony code this is logical, as more file operations are involved. And file operations are most likely to create more inaccurate timings under load.

And surprisingly the results on the live system are about 30% better than on my machine. I did not expect that.

So if you have a heavy ajax action that you would like to leave as it its, but search a way to execute it faster. Have a look at François tip and my variation, and choose what suits you best. And then try it of course. Do not trust anybody on performance tips until you tried them in your scenario :-)

Published by Fabian on 06 Mar 2008

iPhone becomes non business smartphone

German IT news site Golem reports that the iPhone will become a smartphone. Mid 2008 Apple will allow users to install custom software. Okay, again: Apple will allow certified software to be downloaded from iTunes. 30% of the price will go directly to Apple.

It seems that Apple still does not target companies. While the model might be suitable for selling games and stuff, I had hoped that with the announced possibility of installing applications we can get VPN software, terminal software and business applications on the iPhone.

As a application developer I would love the iPhone because it is in my opinion superior suitable to hose bussiness applications, either native and web. But until Apple allows us corporate software distribution this will still be the Symbian/WinCE/blackberry market.

Perhaps the iPhone as such shall be only for lifestyle, not for business?

It gets even more interesting, because on the other hand Apple announced that they will support Microsofts ActiveSync for enabling push-email from Exchange servers.

Gosh.. Apple what is your roadmap? Where shall the iPhone go?

Next »