Optimization for Faster Loops in PHP

As with all programming languages, in PHP there are always several ways to do something. As with most, there are differences in performance depending on how something is done – usually as a trade-off for code neatness. Take for example, running through an array.

$key = array_keys($aHash);
$size = sizeOf($key);
for ($i=0; $i<$size; $i++) $aHash[$key[$i]] .= "a";

Not particularly neat, but by far the fastest way to do the job. If we start to reduce the amount of code, we can find ourselves with this:

while(list($key) = each($aHash)) $aHash[$key] .= "a";

Although neater, the problem we’ve generated here is that for each time the loop runs, we’re relying on return values from the list() and each() functions. Our previous loop ran these at the start. Test have shown this method to be over 200% slower that our first version.

If we take this further, and use the notoriously inefficient foreach() function for our loop, we could be up to 600% slower than our original.

foreach($aHash as $key=>$val) $aHash[$key] .= "a";

So if the problem stems from the inclusion of unnecessary functions inside loops, the extent of it is linked to how long it takes those functions to execute. Comparing the two lines of code, one with the length of the array pre-calculated:

$size = count($array);
for ($i=0; $i<$size; $i++) {

and the other with an inline function:

for($i = 0; $i < count($array); $i++) {

It may surprise you to know that most tests put the latter at around five hundred times slower the former, and that's just using a simple count() function.

For more information on the various benchmarks mentioned within this post and others, see PHP Bench.

Enabling The Root User on Linux and Mac OS X

Mac OS X and certain distributions of Linux do not have the root user enabled by default. You can use the “sudo” command to assume root privileges when you need it, but this inconvenient at best. So, enable the root user:

Mac OS X

Open the “Directory Utility” from inside “Utilities”, which is in your “Applications” folder. Click the lock icon in the bottom-left of the window and enter your admin password when prompted.

Enabling the Root Account in Mac OS X's Directory Utility

Enabling the Root Account in Mac OS X's Directory Utility

From the “Edit” menu, select “Enable Root User”. Enter a password for the root account to use, and then click OK. If you need to disable it, repeat the process, selected “Disable Root User” from the “Edit” menu.

Linux

In order to enable the root account in Linux, issue the following command in a terminal window:

sudo passwd root

This will essentially use super-user privileges from sudo to set a new password for the root account. In order to disable the root account again, issue the command:

sudo password -l root

Becoming Root

Now you’ve enabled your root account, whenever you’re in a terminal window, you will be able to issue the command:

su root

This will start a new shell with you logged in as root.

Changing The Default Mac OS X Screenshot Location

Mac OS X has some fantastic screenshot capabilities built into it, but there is one annoyance that doesn’t seem particularly well thought through – putting all the screenshots on the Desktop. This can be changed through the use of the “defaults” command in the Terminal. Here’s a decent setup for it:

Open your home folder, then “Pictures” and create a folder called “Screenshots”. Open up Terminal and issue the following command:

defaults write com.apple.screencapture location /Users/YourUsername/Pictures/Screenshots

If you’re a Leopard user, do what I do and drag this screenshots folder into the stacks area of your dock then Ctrl-Click the stack and select “Grid” from the “View content as”. You will now be able to see all of the screenshots you’ve made recently by clicking the stack. If you’re using Tiger, you can do the same and then Ctrl-Click to see what’s in the folder.

CSS3 Box-Model: Padding and Other Info

A little while back, I posted some information on revisions to the CSS box-model in CSS 3. I thought I’d follow up with some more information that wasn’t in that post regarding another option for the property as well as which properties in affects.

In my first post, I mentioned that setting the “box-sizing: ” property to “border-box” would allow you specify “height: ” and “width: ” properties that include any padding or border added to the element. To use the existing method of sizing, you can set it to “content-box”, which is the default. What I didn’t mention is a third option, “padding-box”, which would as you expect mean that the height and width include the padding but not the border.

Also, having experimented with it for a bit, I’ve found that the various minimum and maximum properties (e.g. “min-height: “, “max-wdith: “) also adhere the revised box-model

Here’s a quick summary of the compatibility of the different browsers.

Browser Property Name
Firefox 3+ -moz-box-sizing:
Opera 9 box-sizing:
Safari 3 -webkit-box-sizing:
Internet Explorer 8 box-sizing:

The Different Rendering Engines

Although there are multitude of browsers out there, sense does prevail (sort of) in that they are all based on handful on rendering engines. This is the important part of a Web browser that actually deals with the layout of the HTML and CSS – many browser will share a rendering engine and then add their own menus, toolbars etc around it. Here’s a quick run-down of the rendering engines and which browsers they are used in.

Gecko – an open-source and highly standards-compliant rendering engine used in Firefox and it’s derivatives Camino and Seamonkey, as well Epiphany.

Trident – the one that causes all the problem. Microsoft’s rendering engine sits behind Internet Explorer but also forms the basis for Microsoft’s ActiveX wbe controls. This means it also finds its way into various applications such as AOL Explorer, Real Player, MSN and the Yahoo! Browser.

KHTML – an open-source component developed by the KDE team (a Linux desktop environment). It is only really used by KDE’s file / Web browser Konqueror, although it is very standards compliant and very similar to WebKit in it’s rendering, so does not present many problems in cross-browser testing. KHTML was actually the first rendering engine to pass the Acid2 test.

WebKit – originally forked from KHTML by Apple in order to bring it to the OS X platform, it ended up not being able to stay in-sync with KHTML and is now considered a separate engine. It was re-open-sourced in 2005 and is currently in use in Apple’s Safari (all platforms), Google Chrome, Shhira, Omniweb, iCab and Epiphany.

Presto – the Presto engine is developed by Opera and used solely by the Opera Browser. However, derivatives of the Opera browser are starting to be used in lots of home devices such as the Nintendo Wii and DS.

Double margins in Internet Explorer

IE6 has a very strange bug with an even stranger solution, whereby it doubles margins on floated block elements. Say you have a parent <div> that will contain a 3×3 grid of nine <divs>. You want a ten pixel gap between everything, so we give them all a 5px margin and then add 5px padding to the parent <div>. In theory, and in practive in most, browsers this gives us our 10px gaps. But in IE6, we come across a problem whereby the gaps on the outside are doubled.

I don’t think anyone’s entirely sure why this happens or why the solution works. The simple way around it is to add “display: inline; ” to the child <div> elements. In theory this should have no effect – when we float these child divs we force them into being displayed as block elements, and then browser should not pay any attention to what the “display: ” attribute says, unless it’s “none” or “hidden”. Whatsmore, even when IE sees the “display: inline;” declaration, although it sorts out the problem, it still renders our divs as block elements.

CSS3: Box-model… simplified

Probably the biggest change in CSS3 are optional changes to the box-model and how browsers render heights and widths. Using the traditional box-model, heights and widths of boxes set the dimensions of the internal content area. Any padding, borders or margins added to that box increase the width beyond what has been specifically declared.

This will still be the default – setting the “box-sizing: ” attribute to “content-box”. However, set the “box-sizing: ” attribute to “border-box ” and all borders and padding will be subtracted from the declared heights and widths when rendering.

Support is already available for this in Opera using the “box-sizing: ” attribute. Firefox and Safari support this as well, but using the respective experimental prefixes, “-moz-box-sizing: ” and “-webkit-box-sizing: “.

CSS3: Text Overflow

One of the best things about CSS3 is how it handles overflowing text. Even if you introduce character limits in the programming stage, it’s still very difficult to get this right. When using varibale-width fonts, the odd character can overflow from a block and cause havoc with your layout. To be safe you can set the “overflow: ” attribute to “hidden” but this will literally hide anything that overflow, occassionally clipping the middle of a character.

The “text-overflow: ” property in CSS3 aims to rectify that by giving you greater control on how text is rendered. You can set it top clip to do exactly what we talking about above – hide the rest of the text. Or you can use “ellipsis”, to add a “…” to the end of the text when it overflows, or “ellipsis-word” to add “…” to the last renderable word.

Remove Bold Text in Safari

Many people complain about Safari rendering text as bold, even when the “font-weight: ” property is set to “normal”. The truth is you can fiddle with the sizes and font-weights forever to no avail. What’s causing the problem is the as-yet-not-standard “text-shadow: ” property.

Part of the upcoming CSS3 specification, the “text-shadow: ” property is used for creating a drop-shadow on your text. Safari has supported this property since Version 1.0 and uses it by default to provide a quasi anti-aliasing effect on the text. So, in order to get Safari’s text to render without it, and therefore more similarly to the other browsers, add the following to the CSS declaration:

text-shadow: 0px 0px;

CSS3: Text Shadowing

With CSS3 there is no longer the need to use an image editor to create drop shadows on your text. Using the “text-shadow: ” property you can add shadows of any colour, at any horizontal or vertical displacement and even add a blur to it. Take, for example, the following:

h1 {
text-shadow: 10px 5px 5px #00000;
}

will create a black drop-shadow for our <h1> elements, 10px to the right and 5px down from the actual text. The third value will apply a 5px blur to the shadow.

There is support for text-shadow in Opera 9.5 and the upcoming Firefox 3.1. This property has existed in Safari since Version 1.0 and is used by Safari as a sort of anti-aliasing effect for it’s text.