Categories
Posts

Efficient PHP: Don’t Abuse dirname( __FILE__ )

Every now and then I run across a chunk of PHP code at the top of a file that looks something like this:

[sourcecode lang=”php”]
require dirname( __FILE__ ) . ‘/path/to/something.php’;
require dirname( __FILE__ ) . ‘/path/to/another.php’;
require dirname( __FILE__ ) . ‘/path/to/me-too.php’;
require dirname( __FILE__ ) . ‘/path/to/sure-why-not.php’;
require dirname( __FILE__ ) . ‘/path/to/kitchen-sink.php’;
[/sourcecode]

and what jumps out at me is the repeated use of dirname( __FILE__ ) for each require statement (for now we’ll avoid asking why anyone would need to include the kitchen-sink in their code base). My gut instinct is to call dirname( __FILE__ ) once, save that in a variable and then reference the variable to build the path. Not wanting to go on instinct alone I put together a small test to see if it really would make any difference.

The contrived test code will compare approach A:

[sourcecode lang=”php”]
$var = dirname( __FILE__ ) . ‘/path/to/something.php’;
$var = dirname( __FILE__ ) . ‘/path/to/another.php’;
$var = dirname( __FILE__ ) . ‘/path/to/me-too.php’;
$var = dirname( __FILE__ ) . ‘/path/to/sure-why-not.php’;
$var = dirname( __FILE__ ) . ‘/path/to/kitchen-sink.php’;
[/sourcecode]

with approach B:

[sourcecode lang=”php”]
$path = dirname( __FILE__ );

$var = $path . ‘/path/to/something.php’;
$var = $path . ‘/path/to/another.php’;
$var = $path . ‘/path/to/me-too.php’;
$var = $path . ‘/path/to/sure-why-not.php’;
$var = $path . ‘/path/to/kitchen-sink.php’;
[/sourcecode]

I’m not testing with require in an effort to focus just on the difference repeated dirname( __FILE__ ) calls make, not how fast the filesystem can slurp in PHP libraries.

VLD

My first test was to pass each approach through VLD to see how much “work” PHP was doing. For that I pulled out the number of operations needed for each approach:

approach A: 37 ops
approach B: 23 ops

Calling dirname( __FILE__ ) once required 37% fewer operations. This is a bit of blunt measurement since it doesn’t attempt to give individual weights to the different operations, but it gives a good general view. The rule of thumb is that fewer ops is better than more ops.

Time

I tried running each approach in a simple loop, but it always ran so quickly that I didn’t see any useful difference.

Memory

Next up was a look at memory_get_peak_usage. Turns out there was a small difference:

approach A: 57,312 bytes
approach B: 56,992 bytes

Sure 320 bytes isn’t a big deal in the world of servers with 16GB of memory, but it’s one more reason why approach B is just that tiny bit better.

Conclusion

If you see this pattern creeping into your code base and you can easily convert it then you’ll likely be better off for it. Remember that everything is a trade off though, if it takes you several hours to go through and make this kind of change it may not be worth it.

I’d certainly file this away for new projects though so that you can avoid repetitive dirname( __FILE__ ) calls from the start. For that matter, if you can get away with running on 5.3 or higher then you’d probably want to skip this entirely and look at using the new __DIR__ constant. I haven’t tested how it compares to the two approaches listed above, but I’d expect it to be at least as good as approach B, perhaps even better.

For reference I tested this using PHP 5.2.10-2ubuntu6.4 with Suhosin-Patch 0.9.7 (cli) (built: Jan 6 2010 22:41:56). Your specific version of PHP may behave differently.