<?php

define('NUM_TESTS', 10000);
define('REPEATS', 3);

for ($j = 1; $j <= 4 * REPEATS; $j++)
{
	$ts = microtime();
	
	if (($j + 3) % 4 === 0)
	{
		for ($i = 0; $i < NUM_TESTS; ++$i) {
			if (true)
			{
				$a = new stdClass(array('a' => 1));
			}
		}
	}
	if (($j + 2) % 4 === 0)
	{
		for ($i = 0; $i < NUM_TESTS; ++$i) {
			if (true)
			{
				$a = new Exception('something');
			}
		}
	}
	if (($j + 1) % 4 === 0)
	{
		for ($i = 0; $i < NUM_TESTS; ++$i) {
			try
			{
				$a = new Exception('something');
			}
			catch (Exception $e) {}
		}
	}
	if (($j + 0) % 4 === 0)
	{
		for ($i = 0; $i < NUM_TESTS; ++$i) {
			try
			{
				throw new Exception('something');
			}
			catch (Exception $e) {}
		}
	}
	$t[$j] = (microtime() - $ts);
}
?>

<table border="1" cellpadding="2" width="600" style="font: 12px Arial;">
<?php
	for($i = 1; $i <= 4 * REPEATS; $i = $i + 4):
?>
<tr>
	<td></td>
	<td>New Obj</td>
	<td>New Exception</td>
	<td>Try instead of if</td>
	<td>Catch Exception</td>
</tr>
<tr>
	<td>Time</td>
	<td><?php echo $t[$i]; ?></td>
	<td><?php echo $t[$i+1]; ?></td>
	<td><?php echo $t[$i+2]; ?></td>
	<td><?php echo $t[$i+3]; ?></td>
</tr>
<tr>
	<td>Slower than previous</td>
	<td>n/a</td>
	<td><?php echo $t[$i+1] - $t[$i]; ?></td>
	<td><?php echo $t[$i+2] - $t[$i+1]; ?></td>
	<td><?php echo $t[$i+3] - $t[$i+2]; ?></td>
</tr>
<tr>
	<td>Perc slower</td>
	<td>n/a</td>
	<td><?php echo round((($t[$i+1] - $t[$i]) / $t[$i]) * 100, 2); ?></td>
	<td><?php echo round((($t[$i+2] - $t[$i+1]) / $t[$i+1]) * 100, 2); ?></td>
	<td><?php echo round((($t[$i+3] - $t[$i+2]) / $t[$i+2]) * 100, 2); ?></td>
</tr>
<?php
	endfor;
?>
</table>

We have all often heard that Exceptions are slow. I had a discussion with FrenkyNet about the FuelPHP Validation class's usage of Exceptions, he ended up doing some speed testing to see if it led to a significant slowdown. I took his test and improved them a bit.

Testcases

  1. this is the reference, uses if and creates a stdClass object
  2. tests how much creating an exception object costs
  3. tests how much trying costs
  4. tests how much catching costs

Results

Avarage times for running the cases 10,000 times

  • Avarage 1: 0.0082s
  • Avarage 2: 0.0432s
  • Avarage 3: 0.0428s
  • Avarage 4: 0.0471s

Observations

  • It's about 4 to 4.6 times slower to create an Exception compared to creating a stdClass object
  • Using a successfull try is actually a little faster (though negligable) than if
  • Catching a failed try is about 10% slower than successfull try

Thoughts

This both debunks and confirms preconceptions about using try-catch. On its own try-catch performs very well, but creating the exception necessary for throwing is slow in comparisson. This should be put in perspective though: it took my shared hosting 0.043 seconds to create 10,000 Exceptions. That's not slow.

My personal opinion is that exceptions can be very usefull and are acceptable to use (under the right circumstances) even when you know that there's an exception thrown quite often. The overhead created by other parts of your application will often make the 0.0000043 seconds needed to create the Exception object negligable.

Very late addition

I did some more testing: you can save a little bit of resources by not calling the parent constructor if you don't need the debug info. SPL exceptions were a little more expensive than the normal ones.